mirror of
https://github.com/ossu/computer-science.git
synced 2025-02-26 09:21:13 -05:00
Remove personal files
This commit is contained in:
parent
d208d53d5e
commit
2e375602c3
@ -1,14 +0,0 @@
|
|||||||
# [Introduction to Computer Science and Programming](http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-00sc-introduction-to-computer-science-and-programming-spring-2011/)
|
|
||||||
|
|
||||||
## Unit 1
|
|
||||||
|
|
||||||
- **INTRODUCTION TO 6.00** ✔
|
|
||||||
- **CORE ELEMENTS OF A PROGRAM** ✔
|
|
||||||
- **PROBLEM SOLVING** ✔
|
|
||||||
- MACHINE INTERPRETATION OF A PROGRAM ✍
|
|
||||||
- OBJECTS IN PYTHON
|
|
||||||
- RECURSION
|
|
||||||
- DEBUGGING
|
|
||||||
- EFFICIENCY AND ORDER OF GROWTH
|
|
||||||
- MEMORY AND SEARCH METHODS
|
|
||||||
- QUIZ 1
|
|
@ -1,44 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Write a program that does the following in order:
|
|
||||||
|
|
||||||
1. Asks the user to enter his/her date of birth.
|
|
||||||
2. Asks the user to enter his/her last name.
|
|
||||||
3. Prints out the user’s last name and date of birth, in that order.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
var answers = 0;
|
|
||||||
var birthDate = '';
|
|
||||||
var lastName = '';
|
|
||||||
|
|
||||||
process.stdin.resume();
|
|
||||||
|
|
||||||
console.log( 'What is your birth date?' );
|
|
||||||
process.stdin.setEncoding( 'utf8' );
|
|
||||||
|
|
||||||
process.stdin.on( 'data', function( input ) {
|
|
||||||
|
|
||||||
if ( answers === 0 ) {
|
|
||||||
|
|
||||||
birthDate = input;
|
|
||||||
answers += 1;
|
|
||||||
|
|
||||||
console.log( 'What is your last name?' );
|
|
||||||
|
|
||||||
} else if ( answers === 1 ) {
|
|
||||||
|
|
||||||
lastName = input;
|
|
||||||
|
|
||||||
console.log(
|
|
||||||
'================\n<< Informations >>\n' +
|
|
||||||
'Birth date: ' + birthDate + '\n' +
|
|
||||||
'Last Name: ' + lastName + '\n' +
|
|
||||||
'Bye!'
|
|
||||||
);
|
|
||||||
|
|
||||||
process.exit();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
@ -1,88 +0,0 @@
|
|||||||
/*
|
|
||||||
*
|
|
||||||
* Author: Eric Douglas
|
|
||||||
* Finished: 20/06/2015
|
|
||||||
*
|
|
||||||
* Write a program to calculate the credit card balance after one year
|
|
||||||
* if a person only pays the minimum monthly payment required by the credit
|
|
||||||
* card company each month.
|
|
||||||
*
|
|
||||||
* Use raw_input() to ask for the following three floating point numbers:
|
|
||||||
*
|
|
||||||
* 1. the outstanding balance on the credit card
|
|
||||||
* 2. annual interest rate
|
|
||||||
* 3. minimum monthly payment rate
|
|
||||||
*
|
|
||||||
* For each month, print the minimum monthly payment, remaining balance,
|
|
||||||
* principle paid in the format shown in the test cases below.
|
|
||||||
* All numbers should be rounded to the nearest penny. Finally, print the result,
|
|
||||||
* which should include the total amount paid that year and the remaining balance.
|
|
||||||
*
|
|
||||||
* - Minimum monthly payment = Minimum monthly payment rate x Balance
|
|
||||||
* (Minimum monthly payment gets split into interest paid and principal paid)
|
|
||||||
* - Interest Paid = Annual interest rate / 12 months x Balance
|
|
||||||
* - Principal paid = Minimum monthly payment – Interest paid
|
|
||||||
* - Remaining balance = Balance – Principal paid
|
|
||||||
*
|
|
||||||
* http://bit.ly/1S6Tdys
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
var prompt = require( 'prompt' );
|
|
||||||
|
|
||||||
prompt.start();
|
|
||||||
prompt.get([
|
|
||||||
{
|
|
||||||
name : 'balance',
|
|
||||||
description : 'Enter the outstanding balance on your credit card'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name : 'interest',
|
|
||||||
description : 'Enter the annual credit card interest rate as a decimal'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name : 'minimum',
|
|
||||||
description : 'Enter the minimum monthly payment rate as a decimal'
|
|
||||||
}
|
|
||||||
], function( err, results ) {
|
|
||||||
|
|
||||||
// constants
|
|
||||||
var PERIOD = 12;
|
|
||||||
|
|
||||||
// input variables
|
|
||||||
var initialBalance = parseFloat( results.balance );
|
|
||||||
var interest = parseFloat( results.interest );
|
|
||||||
var minPayment = parseFloat( results.minimum );
|
|
||||||
|
|
||||||
// output variables
|
|
||||||
var month = 1;
|
|
||||||
var minMonthlyPayment = 0;
|
|
||||||
var principalPaid = 0;
|
|
||||||
var actualBalance = initialBalance;
|
|
||||||
|
|
||||||
// helper variables
|
|
||||||
var actualMinPayment = 0;
|
|
||||||
var actualInterest = 0;
|
|
||||||
var totalPaid = 0;
|
|
||||||
|
|
||||||
while( month <= PERIOD ) {
|
|
||||||
|
|
||||||
actualMinPayment = minPayment * actualBalance;
|
|
||||||
actualInterest = ( interest / 12 ) * actualBalance;
|
|
||||||
principalPaid = actualMinPayment - actualInterest;
|
|
||||||
actualBalance -= principalPaid;
|
|
||||||
totalPaid += actualMinPayment;
|
|
||||||
|
|
||||||
console.log( 'Month:', month );
|
|
||||||
console.log( 'Minimum monthly payment:', actualMinPayment.toFixed( 2 ));
|
|
||||||
console.log( 'Principal paid:', principalPaid.toFixed( 2 ));
|
|
||||||
console.log( 'Remaining balance', actualBalance.toFixed( 2 ), '\n' );
|
|
||||||
|
|
||||||
month += 1;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log( '======= RESULT =======');
|
|
||||||
console.log( 'Total amount paid:', totalPaid.toFixed( 2 ));
|
|
||||||
console.log( 'Remaining balance', actualBalance.toFixed( 2 ), '\n' );
|
|
||||||
|
|
||||||
});
|
|
@ -1,49 +0,0 @@
|
|||||||
/*
|
|
||||||
*
|
|
||||||
* Author: Eric Douglas
|
|
||||||
* Finished:
|
|
||||||
*
|
|
||||||
* Paying Debt Off In a Year - BISECTION METHOD
|
|
||||||
*
|
|
||||||
* - interest is compounded monthly according to the balance at
|
|
||||||
* the start of the month
|
|
||||||
* - monthly payment must be a multiple of $10 and is the same for all months
|
|
||||||
* - it is possible for the balance to become negative using this scheme
|
|
||||||
*/
|
|
||||||
|
|
||||||
var prompt = require( 'prompt' );
|
|
||||||
|
|
||||||
prompt.start();
|
|
||||||
prompt.get([
|
|
||||||
{
|
|
||||||
name : 'balance',
|
|
||||||
description : 'Enter the outstanding balance on your credit card'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name : 'interest',
|
|
||||||
description : 'Enter the annual credit card interest rate as a decimal'
|
|
||||||
}
|
|
||||||
], function( err, results ) {
|
|
||||||
|
|
||||||
// input variables
|
|
||||||
var balance = parseFloat( results.balance );
|
|
||||||
var interest = parseFloat( results.interest );
|
|
||||||
|
|
||||||
// output variables
|
|
||||||
var parcel = 0;
|
|
||||||
var months = 0;
|
|
||||||
var paid = 0;
|
|
||||||
|
|
||||||
// helper variables
|
|
||||||
var step = 0.01;
|
|
||||||
var min = 0;
|
|
||||||
var max = 0;
|
|
||||||
var guesses = 0;
|
|
||||||
|
|
||||||
// Results
|
|
||||||
console.log( '======= RESULT =======');
|
|
||||||
console.log( 'Monthly payment to pay off debt in 1 year:', parcel );
|
|
||||||
console.log( 'Number of months needed:', months );
|
|
||||||
console.log( 'Balance', paid );
|
|
||||||
|
|
||||||
});
|
|
@ -1,59 +0,0 @@
|
|||||||
/*
|
|
||||||
*
|
|
||||||
* Author: Eric Douglas
|
|
||||||
* Finished: 2015-06-21
|
|
||||||
*
|
|
||||||
* Paying Debt Off In a Year
|
|
||||||
*
|
|
||||||
* - interest is compounded monthly according to the balance at
|
|
||||||
* the start of the month
|
|
||||||
* - monthly payment must be a multiple of $10 and is the same for all months
|
|
||||||
* - it is possible for the balance to become negative using this scheme
|
|
||||||
*/
|
|
||||||
|
|
||||||
var prompt = require( 'prompt' );
|
|
||||||
|
|
||||||
prompt.start();
|
|
||||||
prompt.get([
|
|
||||||
{
|
|
||||||
name : 'balance',
|
|
||||||
description : 'Enter the outstanding balance on your credit card'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name : 'interest',
|
|
||||||
description : 'Enter the annual credit card interest rate as a decimal'
|
|
||||||
}
|
|
||||||
], function( err, results ) {
|
|
||||||
|
|
||||||
// constants
|
|
||||||
var PERIOD = 12;
|
|
||||||
|
|
||||||
// input variables
|
|
||||||
var initialBalance = parseFloat( results.balance );
|
|
||||||
var interest = parseFloat( results.interest );
|
|
||||||
|
|
||||||
// helper variables
|
|
||||||
var monthsNeeded = 0;
|
|
||||||
var totalBalance = initialBalance;
|
|
||||||
var monthInterest = interest / 12;
|
|
||||||
var monthPayment = 10;
|
|
||||||
|
|
||||||
while ( totalBalance > 0 ) {
|
|
||||||
|
|
||||||
totalBalance = ( totalBalance * ( 1 + monthInterest ) - monthPayment );
|
|
||||||
monthsNeeded += 1;
|
|
||||||
|
|
||||||
if ( monthsNeeded >= 12 ) {
|
|
||||||
monthPayment += 10;
|
|
||||||
totalBalance = initialBalance;
|
|
||||||
monthsNeeded = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log( '======= RESULT =======');
|
|
||||||
console.log( 'Monthly payment to pay off debt in 1 year:', monthPayment );
|
|
||||||
console.log( 'Number of months needed:', monthsNeeded );
|
|
||||||
console.log( 'Balance', totalBalance.toFixed( 2 ));
|
|
||||||
|
|
||||||
});
|
|
@ -1,126 +0,0 @@
|
|||||||
// Modules
|
|
||||||
var prompt = require( 'prompt' );
|
|
||||||
|
|
||||||
// // Create a variable x and assign value 3 to it
|
|
||||||
// var x = 3;
|
|
||||||
|
|
||||||
// // Bind x to value 9
|
|
||||||
// x *= x; // or x = x * x;
|
|
||||||
// console.log( x );
|
|
||||||
|
|
||||||
// // read input data from terminal
|
|
||||||
// prompt.start();
|
|
||||||
// prompt.get({
|
|
||||||
// name : 'number',
|
|
||||||
// description : 'Enter a number'
|
|
||||||
// }, function( err, results ) {
|
|
||||||
|
|
||||||
// console.log( results.number );
|
|
||||||
|
|
||||||
// });
|
|
||||||
|
|
||||||
// // Verify if a integer number is even or odd.
|
|
||||||
// // If odd, verify if the number is divisible by 3
|
|
||||||
// // read input data from terminal
|
|
||||||
// prompt.start();
|
|
||||||
|
|
||||||
// prompt.get([
|
|
||||||
// {
|
|
||||||
// name : 'number',
|
|
||||||
// description : 'Enter a integer'
|
|
||||||
// }
|
|
||||||
// ], function( err, results ) {
|
|
||||||
|
|
||||||
// var int = parseInt( results.number, 10 );
|
|
||||||
|
|
||||||
// if ( int % 2 === 0 ) {
|
|
||||||
|
|
||||||
// console.log( int + ' is EVEN' );
|
|
||||||
|
|
||||||
// } else {
|
|
||||||
|
|
||||||
// var msg = int.toString() + ' is ODD';
|
|
||||||
|
|
||||||
// if ( int % 3 !== 0 ) {
|
|
||||||
|
|
||||||
// msg += ' and NOT divisible by 3';
|
|
||||||
|
|
||||||
// }
|
|
||||||
|
|
||||||
// console.log( msg );
|
|
||||||
|
|
||||||
// }
|
|
||||||
|
|
||||||
// });
|
|
||||||
|
|
||||||
// // Find the lowest among three numbers
|
|
||||||
// prompt.start();
|
|
||||||
// prompt.get([
|
|
||||||
// {
|
|
||||||
// name : 'x',
|
|
||||||
// description : 'Enter x'
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// name : 'y',
|
|
||||||
// description : 'Enter y'
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// name : 'z',
|
|
||||||
// description : 'Enter z'
|
|
||||||
// }
|
|
||||||
// ], function( err, results ) {
|
|
||||||
|
|
||||||
// if ( results.x < results.y ) {
|
|
||||||
|
|
||||||
// if ( results.x < results.z ) {
|
|
||||||
// console.log( 'x is least' );
|
|
||||||
// } else {
|
|
||||||
// console.log( 'z is least' );
|
|
||||||
// }
|
|
||||||
|
|
||||||
// } else if ( results.y < results.z ) {
|
|
||||||
|
|
||||||
// console.log( 'y is least' );
|
|
||||||
|
|
||||||
// } else {
|
|
||||||
|
|
||||||
// console.log( 'z is least' );
|
|
||||||
|
|
||||||
// }
|
|
||||||
|
|
||||||
// });
|
|
||||||
|
|
||||||
// Find the cube root of a perfect cube
|
|
||||||
prompt.start();
|
|
||||||
prompt.get([
|
|
||||||
{
|
|
||||||
name : 'x',
|
|
||||||
description : 'Enter a interger'
|
|
||||||
}
|
|
||||||
], function( err, results ) {
|
|
||||||
|
|
||||||
var x = parseInt( results.x, 10 );
|
|
||||||
var ans = 0;
|
|
||||||
|
|
||||||
while ( Math.pow( ans, 3 ) < Math.abs( x )) {
|
|
||||||
|
|
||||||
ans += 1;
|
|
||||||
console.log( 'Current guess:', ans );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( Math.pow( ans, 3 ) !== Math.abs( x )) {
|
|
||||||
|
|
||||||
console.log( x, 'is not a perfect cube' );
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
if ( x < 0 ) {
|
|
||||||
ans = -ans;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log( 'Cube root of ' + x.toString() + ' is ' + ans.toString());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
@ -1,149 +0,0 @@
|
|||||||
// Modules
|
|
||||||
var range = require( 'range' ).range;
|
|
||||||
var prompt = require( 'prompt' );
|
|
||||||
|
|
||||||
// // Find the cube root of a perfect cube
|
|
||||||
// prompt.start();
|
|
||||||
// prompt.get([
|
|
||||||
// {
|
|
||||||
// name : 'x',
|
|
||||||
// description : 'Enter a interger'
|
|
||||||
// }
|
|
||||||
// ], function( err, results ) {
|
|
||||||
|
|
||||||
// var x = parseInt( results.x, 10 );
|
|
||||||
// var ans = 0;
|
|
||||||
|
|
||||||
// while ( Math.pow( ans, 3 ) < Math.abs( x )) {
|
|
||||||
|
|
||||||
// ans += 1;
|
|
||||||
// console.log( 'Current guess:', ans );
|
|
||||||
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if ( Math.pow( ans, 3 ) !== Math.abs( x )) {
|
|
||||||
|
|
||||||
// console.log( x, 'is not a perfect cube' );
|
|
||||||
|
|
||||||
// } else {
|
|
||||||
|
|
||||||
// if ( x < 0 ) {
|
|
||||||
// ans = -ans;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// console.log( 'Cube root of ' + x.toString() + ' is ' + ans.toString());
|
|
||||||
|
|
||||||
// }
|
|
||||||
|
|
||||||
// });
|
|
||||||
|
|
||||||
// // Find the cube root of a perfect cube
|
|
||||||
// prompt.start();
|
|
||||||
// prompt.get([
|
|
||||||
// {
|
|
||||||
// name : 'x',
|
|
||||||
// description : 'Enter a interger'
|
|
||||||
// }
|
|
||||||
// ], function( err, results ) {
|
|
||||||
|
|
||||||
// var x = parseInt( results.x, 10 );
|
|
||||||
// var ans;
|
|
||||||
|
|
||||||
// for ( ans in range( 0, Math.abs( x ) + 1 )) {
|
|
||||||
|
|
||||||
// if ( Math.pow( ans, 3 ) === Math.abs( x )) {
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if ( Math.pow( ans, 3 ) !== Math.abs( x )) {
|
|
||||||
|
|
||||||
// console.log( x + ' is not a perfect cube' );
|
|
||||||
|
|
||||||
// } else {
|
|
||||||
|
|
||||||
// console.log( 'Cube root of ' + x.toString() + ' is ' + ans.toString());
|
|
||||||
|
|
||||||
// }
|
|
||||||
|
|
||||||
// });
|
|
||||||
|
|
||||||
// // Find closest number to be a square root of another number - Brute Force
|
|
||||||
// var x = 25;
|
|
||||||
// var epsilon = 0.01;
|
|
||||||
// var numGuesses = 0;
|
|
||||||
// var ans = 0;
|
|
||||||
|
|
||||||
// while ( Math.abs( Math.pow( ans, 2 ) - x ) >= epsilon && ans <= x ) {
|
|
||||||
|
|
||||||
// ans += 0.00001;
|
|
||||||
// numGuesses += 1;
|
|
||||||
|
|
||||||
// }
|
|
||||||
|
|
||||||
// console.log( 'numGuesses: ' + numGuesses );
|
|
||||||
|
|
||||||
// if ( Math.abs( Math.pow( ans, 2 ) - x >= epsilon )) {
|
|
||||||
// console.log( 'Failed on square root of ' + x.toString());
|
|
||||||
// } else {
|
|
||||||
// console.log( ans.toString() + ' is close to square root of ' + x.toString());
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Find closest number to be a square root of another number - bisection method
|
|
||||||
// var x = 12345;
|
|
||||||
// var epsilon = 0.01;
|
|
||||||
// var numGuesses = 0;
|
|
||||||
// var low = 0;
|
|
||||||
// var high = x;
|
|
||||||
// var ans = ( high + low ) / 2;
|
|
||||||
|
|
||||||
// while ( Math.abs( Math.pow( ans, 2 ) - x ) >= epsilon && ans <= x ) {
|
|
||||||
|
|
||||||
// numGuesses += 1;
|
|
||||||
|
|
||||||
// if ( Math.pow( ans, 2 ) < x ) {
|
|
||||||
|
|
||||||
// low = ans;
|
|
||||||
|
|
||||||
// } else {
|
|
||||||
|
|
||||||
// high = ans;
|
|
||||||
|
|
||||||
// }
|
|
||||||
|
|
||||||
// ans = ( high + low ) / 2;
|
|
||||||
|
|
||||||
// }
|
|
||||||
|
|
||||||
// console.log( 'numGuesses:', numGuesses );
|
|
||||||
// console.log( ans, 'is close to square root of', x );
|
|
||||||
|
|
||||||
// Returns true or false if x is within epsilon of y
|
|
||||||
function withinEpsilon( x, y, epsilon ) {
|
|
||||||
|
|
||||||
console.log( 'Returns true if x is within epsilon of y' );
|
|
||||||
|
|
||||||
return Math.abs( x - y ) <= epsilon;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( withinEpsilon( 25, 26, 1 )) {
|
|
||||||
|
|
||||||
console.log( 'Yes' );
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
console.log( 'No' );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( withinEpsilon( 25, 26, 0.9 )) {
|
|
||||||
|
|
||||||
console.log( 'Yes' );
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
console.log( 'No' );
|
|
||||||
|
|
||||||
}
|
|
@ -1,54 +0,0 @@
|
|||||||
{
|
|
||||||
"passfail": false,
|
|
||||||
"maxerr": 100,
|
|
||||||
|
|
||||||
"browser": false,
|
|
||||||
"node": true,
|
|
||||||
"rhino": false,
|
|
||||||
"couch": true,
|
|
||||||
"wsh": true,
|
|
||||||
"jquery": true,
|
|
||||||
"prototypejs": false,
|
|
||||||
"mootools": false,
|
|
||||||
"dojo": false,
|
|
||||||
|
|
||||||
"devel": false,
|
|
||||||
|
|
||||||
"es5": true,
|
|
||||||
"strict": false,
|
|
||||||
"globalstrict": false,
|
|
||||||
|
|
||||||
"asi": false,
|
|
||||||
"lastsemic": true,
|
|
||||||
"laxbreak": true,
|
|
||||||
"laxcomma": false,
|
|
||||||
"bitwise": false,
|
|
||||||
"boss": false,
|
|
||||||
"curly": true,
|
|
||||||
"eqeqeq": true,
|
|
||||||
"eqnull": false,
|
|
||||||
"evil": false,
|
|
||||||
"expr": false,
|
|
||||||
"forin": false,
|
|
||||||
"immed": false,
|
|
||||||
"latedef": false,
|
|
||||||
"loopfunc": true,
|
|
||||||
"noarg": true,
|
|
||||||
"regexp": true,
|
|
||||||
"regexdash": false,
|
|
||||||
"scripturl": true,
|
|
||||||
"shadow": true,
|
|
||||||
"supernew": true,
|
|
||||||
"undef": true,
|
|
||||||
|
|
||||||
"newcap": true,
|
|
||||||
"noempty": true,
|
|
||||||
"nonew": true,
|
|
||||||
"nomen": false,
|
|
||||||
"onevar": true,
|
|
||||||
"plusplus": false,
|
|
||||||
"sub": true,
|
|
||||||
"trailing": true,
|
|
||||||
"white": false,
|
|
||||||
"indent": 2
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
node_modules/
|
|
||||||
node_modules/*
|
|
||||||
npm-debug.log
|
|
@ -1,10 +0,0 @@
|
|||||||
language: node_js
|
|
||||||
node_js:
|
|
||||||
- 0.8
|
|
||||||
- 0.10
|
|
||||||
|
|
||||||
notifications:
|
|
||||||
email:
|
|
||||||
- travis@nodejitsu.com
|
|
||||||
irc: "irc.freenode.org#nodejitsu"
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
|||||||
|
|
||||||
0.2.7 / 2012-08-30
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Fixed handling of numeric inputs with parseFloat
|
|
||||||
* Fixed overwriting of non-string inputs
|
|
||||||
* Added support for boolean types
|
|
||||||
|
|
||||||
0.2.6 / 2012-08-12
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Added allowance of empty default values
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
|||||||
Copyright (c) 2010 Nodejitsu Inc.
|
|
||||||
|
|
||||||
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.
|
|
317
computer-science/01-introduction-to-cs-and-programming-mit/src/node_modules/prompt/README.md
generated
vendored
317
computer-science/01-introduction-to-cs-and-programming-mit/src/node_modules/prompt/README.md
generated
vendored
@ -1,317 +0,0 @@
|
|||||||
# prompt [](http://travis-ci.org/flatiron/prompt)
|
|
||||||
|
|
||||||
A beautiful command-line prompt for node.js
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
* prompts the user for input
|
|
||||||
* supports validation and defaults
|
|
||||||
* hides passwords
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
Using prompt is relatively straight forward. There are two core methods you should be aware of: `prompt.get()` and `prompt.addProperties()`. There methods take strings representing property names in addition to objects for complex property validation (and more). There are a number of [examples][0] that you should examine for detailed usage.
|
|
||||||
|
|
||||||
### Getting Basic Prompt Information
|
|
||||||
Getting started with `prompt` is easy. Lets take a look at `examples/simple-prompt.js`:
|
|
||||||
|
|
||||||
``` js
|
|
||||||
var prompt = require('prompt');
|
|
||||||
|
|
||||||
//
|
|
||||||
// Start the prompt
|
|
||||||
//
|
|
||||||
prompt.start();
|
|
||||||
|
|
||||||
//
|
|
||||||
// Get two properties from the user: username and email
|
|
||||||
//
|
|
||||||
prompt.get(['username', 'email'], function (err, result) {
|
|
||||||
//
|
|
||||||
// Log the results.
|
|
||||||
//
|
|
||||||
console.log('Command-line input received:');
|
|
||||||
console.log(' username: ' + result.username);
|
|
||||||
console.log(' email: ' + result.email);
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
This will result in the following command-line output:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ node examples/simple-prompt.js
|
|
||||||
prompt: username: some-user
|
|
||||||
prompt: email: some-user@some-place.org
|
|
||||||
Command-line input received:
|
|
||||||
username: some-user
|
|
||||||
email: some-user@some-place.org
|
|
||||||
```
|
|
||||||
|
|
||||||
### Prompting with Validation, Default Values, and More (Complex Properties)
|
|
||||||
In addition to prompting the user with simple string prompts, there is a robust API for getting and validating complex information from a command-line prompt. Here's a quick sample:
|
|
||||||
|
|
||||||
``` js
|
|
||||||
var schema = {
|
|
||||||
properties: {
|
|
||||||
name: {
|
|
||||||
pattern: /^[a-zA-Z\s\-]+$/,
|
|
||||||
message: 'Name must be only letters, spaces, or dashes',
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
password: {
|
|
||||||
hidden: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// Start the prompt
|
|
||||||
//
|
|
||||||
prompt.start();
|
|
||||||
|
|
||||||
//
|
|
||||||
// Get two properties from the user: email, password
|
|
||||||
//
|
|
||||||
prompt.get(schema, function (err, result) {
|
|
||||||
//
|
|
||||||
// Log the results.
|
|
||||||
//
|
|
||||||
console.log('Command-line input received:');
|
|
||||||
console.log(' name: ' + result.name);
|
|
||||||
console.log(' password: ' + result.password);
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
Pretty easy right? The output from the above script is:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ node examples/property-prompt.js
|
|
||||||
prompt: name: nodejitsu000
|
|
||||||
error: Invalid input for name
|
|
||||||
error: Name must be only letters, spaces, or dashes
|
|
||||||
prompt: name: Nodejitsu Inc
|
|
||||||
prompt: password:
|
|
||||||
Command-line input received:
|
|
||||||
name: Nodejitsu Inc
|
|
||||||
password: some-password
|
|
||||||
```
|
|
||||||
|
|
||||||
## Valid Property Settings
|
|
||||||
`prompt` understands JSON-schema with a few extra parameters and uses [revalidator](https://github.com/flatiron/revalidator) for validation.
|
|
||||||
|
|
||||||
Here's an overview of the properties that may be used for validation and prompting controls:
|
|
||||||
|
|
||||||
``` js
|
|
||||||
{
|
|
||||||
description: 'Enter your password', // Prompt displayed to the user. If not supplied name will be used.
|
|
||||||
type: 'string', // Specify the type of input to expect.
|
|
||||||
pattern: /^\w+$/, // Regular expression that input must be valid against.
|
|
||||||
message: 'Password must be letters', // Warning message to display if validation fails.
|
|
||||||
hidden: true, // If true, characters entered will not be output to console.
|
|
||||||
default: 'lamepassword', // Default value to use if no value is entered.
|
|
||||||
required: true // If true, value entered must be non-empty.
|
|
||||||
before: function(value) { return 'v' + value; } // Runs before node-prompt callbacks. It modifies user's input
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Alternatives to `pattern` include `format` and `conform`, as documented in [revalidator](https://github.com/flatiron/revalidator).
|
|
||||||
|
|
||||||
Using `type: 'array'` has some special cases.
|
|
||||||
|
|
||||||
- `description` will not work in the schema if `type: 'array'` is defined.
|
|
||||||
- `maxItems` takes precedence over `minItems`.
|
|
||||||
- Arrays that do not have `maxItems` defined will require users to `SIGINT` (`^C`) before the array is ended.
|
|
||||||
- If `SIGINT` (`^C`) is triggered before `minItems` is met, a validation error will appear. This will require users to `SIGEOF` (`^D`) to end the input.
|
|
||||||
|
|
||||||
For more information on things such as `maxItems` and `minItems`, refer to the [revalidator](https://github.com/flatiron/revalidator) repository.
|
|
||||||
|
|
||||||
### Alternate Validation API:
|
|
||||||
|
|
||||||
Prompt, in addition to iterating over JSON-Schema properties, will also happily iterate over an array of validation objects given an extra 'name' property:
|
|
||||||
|
|
||||||
```js
|
|
||||||
var prompt = require('../lib/prompt');
|
|
||||||
|
|
||||||
//
|
|
||||||
// Start the prompt
|
|
||||||
//
|
|
||||||
prompt.start();
|
|
||||||
|
|
||||||
//
|
|
||||||
// Get two properties from the user: username and password
|
|
||||||
//
|
|
||||||
prompt.get([{
|
|
||||||
name: 'username',
|
|
||||||
required: true
|
|
||||||
}, {
|
|
||||||
name: 'password',
|
|
||||||
hidden: true,
|
|
||||||
conform: function (value) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}], function (err, result) {
|
|
||||||
//
|
|
||||||
// Log the results.
|
|
||||||
//
|
|
||||||
console.log('Command-line input received:');
|
|
||||||
console.log(' username: ' + result.username);
|
|
||||||
console.log(' password: ' + result.password);
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
### Backward Compatibility
|
|
||||||
|
|
||||||
Note that, while this structure is similar to that used by prompt 0.1.x, that the object properties use the same names as in JSON-Schema. prompt 0.2.x is backward compatible with prompt 0.1.x except for asynchronous validation.
|
|
||||||
|
|
||||||
### Skipping Prompts
|
|
||||||
|
|
||||||
Sometimes power users may wish to skip promts and specify all data as command line options.
|
|
||||||
if a value is set as a property of `prompt.override` prompt will use that instead of
|
|
||||||
prompting the user.
|
|
||||||
|
|
||||||
``` js
|
|
||||||
//prompt-override.js
|
|
||||||
|
|
||||||
var prompt = require('prompt'),
|
|
||||||
optimist = require('optimist')
|
|
||||||
|
|
||||||
//
|
|
||||||
// set the overrides
|
|
||||||
//
|
|
||||||
prompt.override = optimist.argv
|
|
||||||
|
|
||||||
//
|
|
||||||
// Start the prompt
|
|
||||||
//
|
|
||||||
prompt.start();
|
|
||||||
|
|
||||||
//
|
|
||||||
// Get two properties from the user: username and email
|
|
||||||
//
|
|
||||||
prompt.get(['username', 'email'], function (err, result) {
|
|
||||||
//
|
|
||||||
// Log the results.
|
|
||||||
//
|
|
||||||
console.log('Command-line input received:');
|
|
||||||
console.log(' username: ' + result.username);
|
|
||||||
console.log(' email: ' + result.email);
|
|
||||||
})
|
|
||||||
|
|
||||||
//: node prompt-override.js --username USER --email EMAIL
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### Adding Properties to an Object
|
|
||||||
A common use-case for prompting users for data from the command-line is to extend or create a configuration object that is passed onto the entry-point method for your CLI tool. `prompt` exposes a convenience method for doing just this:
|
|
||||||
|
|
||||||
``` js
|
|
||||||
var obj = {
|
|
||||||
password: 'lamepassword',
|
|
||||||
mindset: 'NY'
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Log the initial object.
|
|
||||||
//
|
|
||||||
console.log('Initial object to be extended:');
|
|
||||||
console.dir(obj);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Add two properties to the empty object: username and email
|
|
||||||
//
|
|
||||||
prompt.addProperties(obj, ['username', 'email'], function (err) {
|
|
||||||
//
|
|
||||||
// Log the results.
|
|
||||||
//
|
|
||||||
console.log('Updated object received:');
|
|
||||||
console.dir(obj);
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
### Prompt history
|
|
||||||
You can use the `prompt.history()` method to get access to previous prompt input.
|
|
||||||
|
|
||||||
``` js
|
|
||||||
prompt.get([{
|
|
||||||
name: 'name',
|
|
||||||
description: 'Your name',
|
|
||||||
type: 'string',
|
|
||||||
required: true
|
|
||||||
}, {
|
|
||||||
name: 'surname',
|
|
||||||
description: 'Your surname',
|
|
||||||
type: 'string',
|
|
||||||
required: true,
|
|
||||||
message: 'Please dont use the demo credentials',
|
|
||||||
conform: function(surname) {
|
|
||||||
var name = prompt.history('name').value;
|
|
||||||
return (name !== 'John' || surname !== 'Smith');
|
|
||||||
}
|
|
||||||
}], function(err, results) {
|
|
||||||
console.log(results);
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
## Customizing your prompt
|
|
||||||
Aside from changing `property.message`, you can also change `prompt.message`
|
|
||||||
and `prompt.delimiter` to change the appearance of your prompt.
|
|
||||||
|
|
||||||
The basic structure of a prompt is this:
|
|
||||||
|
|
||||||
``` js
|
|
||||||
prompt.message + prompt.delimiter + property.message + prompt.delimiter;
|
|
||||||
```
|
|
||||||
|
|
||||||
The default `prompt.message` is "prompt," the default `prompt.delimiter` is
|
|
||||||
": ", and the default `property.message` is `property.name`.
|
|
||||||
Changing these allows you to customize the appearance of your prompts! In
|
|
||||||
addition, prompt supports ANSI color codes via the
|
|
||||||
[colors module](https://github.com/Marak/colors.js) for custom colors. For a
|
|
||||||
very colorful example:
|
|
||||||
|
|
||||||
``` js
|
|
||||||
var prompt = require("prompt");
|
|
||||||
|
|
||||||
//
|
|
||||||
// Setting these properties customizes the prompt.
|
|
||||||
//
|
|
||||||
prompt.message = "Question!".rainbow;
|
|
||||||
prompt.delimiter = "><".green;
|
|
||||||
|
|
||||||
prompt.start();
|
|
||||||
|
|
||||||
prompt.get({
|
|
||||||
properties: {
|
|
||||||
name: {
|
|
||||||
description: "What is your name?".magenta
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, function (err, result) {
|
|
||||||
console.log("You said your name is: ".cyan + result.name.cyan);
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
If you don't want colors, you can set
|
|
||||||
|
|
||||||
```js
|
|
||||||
var prompt = require('prompt');
|
|
||||||
|
|
||||||
prompt.colors = false;
|
|
||||||
```
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
``` bash
|
|
||||||
$ [sudo] npm install prompt
|
|
||||||
```
|
|
||||||
|
|
||||||
## Running tests
|
|
||||||
|
|
||||||
``` bash
|
|
||||||
$ npm test
|
|
||||||
```
|
|
||||||
|
|
||||||
#### License: MIT
|
|
||||||
#### Author: [Charlie Robbins](http://github.com/indexzero)
|
|
||||||
#### Contributors: [Josh Holbrook](http://github.com/jesusabdullah), [Pavan Kumar Sunkara](http://github.com/pksunkara)
|
|
||||||
|
|
||||||
[0]: https://github.com/flatiron/prompt/tree/master/examples
|
|
@ -1,194 +0,0 @@
|
|||||||
/*--------------------- Layout and Typography ----------------------------*/
|
|
||||||
body {
|
|
||||||
font-family: 'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif;
|
|
||||||
font-size: 15px;
|
|
||||||
line-height: 22px;
|
|
||||||
color: #252519;
|
|
||||||
margin: 0; padding: 0;
|
|
||||||
}
|
|
||||||
a {
|
|
||||||
color: #261a3b;
|
|
||||||
}
|
|
||||||
a:visited {
|
|
||||||
color: #261a3b;
|
|
||||||
}
|
|
||||||
p {
|
|
||||||
margin: 0 0 15px 0;
|
|
||||||
}
|
|
||||||
h4, h5, h6 {
|
|
||||||
color: #333;
|
|
||||||
margin: 6px 0 6px 0;
|
|
||||||
font-size: 13px;
|
|
||||||
}
|
|
||||||
h2, h3 {
|
|
||||||
margin-bottom: 0;
|
|
||||||
color: #000;
|
|
||||||
}
|
|
||||||
h1 {
|
|
||||||
margin-top: 40px;
|
|
||||||
margin-bottom: 15px;
|
|
||||||
color: #000;
|
|
||||||
}
|
|
||||||
#container {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
#background {
|
|
||||||
position: fixed;
|
|
||||||
top: 0; left: 525px; right: 0; bottom: 0;
|
|
||||||
background: #f5f5ff;
|
|
||||||
border-left: 1px solid #e5e5ee;
|
|
||||||
z-index: -1;
|
|
||||||
}
|
|
||||||
#jump_to, #jump_page {
|
|
||||||
background: white;
|
|
||||||
-webkit-box-shadow: 0 0 25px #777; -moz-box-shadow: 0 0 25px #777;
|
|
||||||
-webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomleft: 5px;
|
|
||||||
font: 10px Arial;
|
|
||||||
text-transform: uppercase;
|
|
||||||
cursor: pointer;
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
#jump_to, #jump_wrapper {
|
|
||||||
position: fixed;
|
|
||||||
right: 0; top: 0;
|
|
||||||
padding: 5px 10px;
|
|
||||||
}
|
|
||||||
#jump_wrapper {
|
|
||||||
padding: 0;
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
#jump_to:hover #jump_wrapper {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
#jump_page {
|
|
||||||
padding: 5px 0 3px;
|
|
||||||
margin: 0 0 25px 25px;
|
|
||||||
}
|
|
||||||
#jump_page .source {
|
|
||||||
display: block;
|
|
||||||
padding: 5px 10px;
|
|
||||||
text-decoration: none;
|
|
||||||
border-top: 1px solid #eee;
|
|
||||||
}
|
|
||||||
#jump_page .source:hover {
|
|
||||||
background: #f5f5ff;
|
|
||||||
}
|
|
||||||
#jump_page .source:first-child {
|
|
||||||
}
|
|
||||||
table td {
|
|
||||||
border: 0;
|
|
||||||
outline: 0;
|
|
||||||
}
|
|
||||||
td.docs, th.docs {
|
|
||||||
max-width: 450px;
|
|
||||||
min-width: 450px;
|
|
||||||
min-height: 5px;
|
|
||||||
padding: 10px 25px 1px 50px;
|
|
||||||
overflow-x: hidden;
|
|
||||||
vertical-align: top;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
.docs pre {
|
|
||||||
margin: 15px 0 15px;
|
|
||||||
padding-left: 15px;
|
|
||||||
}
|
|
||||||
.docs p tt, .docs p code {
|
|
||||||
background: #f8f8ff;
|
|
||||||
border: 1px solid #dedede;
|
|
||||||
font-size: 12px;
|
|
||||||
padding: 0 0.2em;
|
|
||||||
}
|
|
||||||
.pilwrap {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
.pilcrow {
|
|
||||||
font: 12px Arial;
|
|
||||||
text-decoration: none;
|
|
||||||
color: #454545;
|
|
||||||
position: absolute;
|
|
||||||
top: 3px; left: -20px;
|
|
||||||
padding: 1px 2px;
|
|
||||||
opacity: 0;
|
|
||||||
-webkit-transition: opacity 0.2s linear;
|
|
||||||
}
|
|
||||||
td.docs:hover .pilcrow {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
td.code, th.code {
|
|
||||||
padding: 14px 15px 16px 25px;
|
|
||||||
width: 100%;
|
|
||||||
vertical-align: top;
|
|
||||||
background: #f5f5ff;
|
|
||||||
border-left: 1px solid #e5e5ee;
|
|
||||||
}
|
|
||||||
pre, tt, code {
|
|
||||||
font-size: 12px; line-height: 18px;
|
|
||||||
font-family: Menlo, Monaco, Consolas, "Lucida Console", monospace;
|
|
||||||
margin: 0; padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*---------------------- Syntax Highlighting -----------------------------*/
|
|
||||||
td.linenos { background-color: #f0f0f0; padding-right: 10px; }
|
|
||||||
span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; }
|
|
||||||
body .hll { background-color: #ffffcc }
|
|
||||||
body .c { color: #408080; font-style: italic } /* Comment */
|
|
||||||
body .err { border: 1px solid #FF0000 } /* Error */
|
|
||||||
body .k { color: #954121 } /* Keyword */
|
|
||||||
body .o { color: #666666 } /* Operator */
|
|
||||||
body .cm { color: #408080; font-style: italic } /* Comment.Multiline */
|
|
||||||
body .cp { color: #BC7A00 } /* Comment.Preproc */
|
|
||||||
body .c1 { color: #408080; font-style: italic } /* Comment.Single */
|
|
||||||
body .cs { color: #408080; font-style: italic } /* Comment.Special */
|
|
||||||
body .gd { color: #A00000 } /* Generic.Deleted */
|
|
||||||
body .ge { font-style: italic } /* Generic.Emph */
|
|
||||||
body .gr { color: #FF0000 } /* Generic.Error */
|
|
||||||
body .gh { color: #000080; font-weight: bold } /* Generic.Heading */
|
|
||||||
body .gi { color: #00A000 } /* Generic.Inserted */
|
|
||||||
body .go { color: #808080 } /* Generic.Output */
|
|
||||||
body .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
|
|
||||||
body .gs { font-weight: bold } /* Generic.Strong */
|
|
||||||
body .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
|
|
||||||
body .gt { color: #0040D0 } /* Generic.Traceback */
|
|
||||||
body .kc { color: #954121 } /* Keyword.Constant */
|
|
||||||
body .kd { color: #954121; font-weight: bold } /* Keyword.Declaration */
|
|
||||||
body .kn { color: #954121; font-weight: bold } /* Keyword.Namespace */
|
|
||||||
body .kp { color: #954121 } /* Keyword.Pseudo */
|
|
||||||
body .kr { color: #954121; font-weight: bold } /* Keyword.Reserved */
|
|
||||||
body .kt { color: #B00040 } /* Keyword.Type */
|
|
||||||
body .m { color: #666666 } /* Literal.Number */
|
|
||||||
body .s { color: #219161 } /* Literal.String */
|
|
||||||
body .na { color: #7D9029 } /* Name.Attribute */
|
|
||||||
body .nb { color: #954121 } /* Name.Builtin */
|
|
||||||
body .nc { color: #0000FF; font-weight: bold } /* Name.Class */
|
|
||||||
body .no { color: #880000 } /* Name.Constant */
|
|
||||||
body .nd { color: #AA22FF } /* Name.Decorator */
|
|
||||||
body .ni { color: #999999; font-weight: bold } /* Name.Entity */
|
|
||||||
body .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
|
|
||||||
body .nf { color: #0000FF } /* Name.Function */
|
|
||||||
body .nl { color: #A0A000 } /* Name.Label */
|
|
||||||
body .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
|
|
||||||
body .nt { color: #954121; font-weight: bold } /* Name.Tag */
|
|
||||||
body .nv { color: #19469D } /* Name.Variable */
|
|
||||||
body .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
|
|
||||||
body .w { color: #bbbbbb } /* Text.Whitespace */
|
|
||||||
body .mf { color: #666666 } /* Literal.Number.Float */
|
|
||||||
body .mh { color: #666666 } /* Literal.Number.Hex */
|
|
||||||
body .mi { color: #666666 } /* Literal.Number.Integer */
|
|
||||||
body .mo { color: #666666 } /* Literal.Number.Oct */
|
|
||||||
body .sb { color: #219161 } /* Literal.String.Backtick */
|
|
||||||
body .sc { color: #219161 } /* Literal.String.Char */
|
|
||||||
body .sd { color: #219161; font-style: italic } /* Literal.String.Doc */
|
|
||||||
body .s2 { color: #219161 } /* Literal.String.Double */
|
|
||||||
body .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
|
|
||||||
body .sh { color: #219161 } /* Literal.String.Heredoc */
|
|
||||||
body .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
|
|
||||||
body .sx { color: #954121 } /* Literal.String.Other */
|
|
||||||
body .sr { color: #BB6688 } /* Literal.String.Regex */
|
|
||||||
body .s1 { color: #219161 } /* Literal.String.Single */
|
|
||||||
body .ss { color: #19469D } /* Literal.String.Symbol */
|
|
||||||
body .bp { color: #954121 } /* Name.Builtin.Pseudo */
|
|
||||||
body .vc { color: #19469D } /* Name.Variable.Class */
|
|
||||||
body .vg { color: #19469D } /* Name.Variable.Global */
|
|
||||||
body .vi { color: #19469D } /* Name.Variable.Instance */
|
|
||||||
body .il { color: #666666 } /* Literal.Number.Integer.Long */
|
|
@ -1,296 +0,0 @@
|
|||||||
<!DOCTYPE html> <html> <head> <title>prompt.js</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> prompt.js </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-1">¶</a> </div> </td> <td class="code"> <div class="highlight"><pre><span class="cm">/*</span>
|
|
||||||
<span class="cm"> * prompt.js: Simple prompt for prompting information from the command line </span>
|
|
||||||
<span class="cm"> *</span>
|
|
||||||
<span class="cm"> * (C) 2010, Nodejitsu Inc.</span>
|
|
||||||
<span class="cm"> *</span>
|
|
||||||
<span class="cm"> */</span>
|
|
||||||
|
|
||||||
<span class="kd">var</span> <span class="nx">events</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'events'</span><span class="p">),</span>
|
|
||||||
<span class="nx">async</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'async'</span><span class="p">),</span>
|
|
||||||
<span class="nx">colors</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'colors'</span><span class="p">),</span>
|
|
||||||
<span class="nx">winston</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'winston'</span><span class="p">),</span>
|
|
||||||
<span class="nx">stdio</span> <span class="o">=</span> <span class="nx">process</span><span class="p">.</span><span class="nx">binding</span><span class="p">(</span><span class="s1">'stdio'</span><span class="p">);</span></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">¶</a> </div> <h3>@private function capitalize (str)</h3>
|
|
||||||
|
|
||||||
<h4>str {string} String to capitalize</h4>
|
|
||||||
|
|
||||||
<p>Capitalizes the string supplied.</p> </td> <td class="code"> <div class="highlight"><pre><span class="kd">function</span> <span class="nx">capitalize</span><span class="p">(</span><span class="nx">str</span><span class="p">)</span> <span class="p">{</span>
|
|
||||||
<span class="k">return</span> <span class="nx">str</span><span class="p">.</span><span class="nx">charAt</span><span class="p">(</span><span class="mi">0</span><span class="p">).</span><span class="nx">toUpperCase</span><span class="p">()</span> <span class="o">+</span> <span class="nx">str</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
|
|
||||||
<span class="p">}</span>
|
|
||||||
|
|
||||||
<span class="kd">var</span> <span class="nx">prompt</span> <span class="o">=</span> <span class="nx">module</span><span class="p">.</span><span class="nx">exports</span> <span class="o">=</span> <span class="nb">Object</span><span class="p">.</span><span class="nx">create</span><span class="p">(</span><span class="nx">events</span><span class="p">.</span><span class="nx">EventEmitter</span><span class="p">.</span><span class="nx">prototype</span><span class="p">);</span>
|
|
||||||
|
|
||||||
<span class="kd">var</span> <span class="nx">logger</span> <span class="o">=</span> <span class="nx">prompt</span><span class="p">.</span><span class="nx">logger</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">winston</span><span class="p">.</span><span class="nx">Logger</span><span class="p">({</span>
|
|
||||||
<span class="nx">transports</span><span class="o">:</span> <span class="p">[</span>
|
|
||||||
<span class="k">new</span> <span class="p">(</span><span class="nx">winston</span><span class="p">.</span><span class="nx">transports</span><span class="p">.</span><span class="nx">Console</span><span class="p">)()</span>
|
|
||||||
<span class="p">]</span>
|
|
||||||
<span class="p">});</span>
|
|
||||||
|
|
||||||
<span class="nx">prompt</span><span class="p">.</span><span class="nx">started</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
|
|
||||||
<span class="nx">prompt</span><span class="p">.</span><span class="nx">paused</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
|
|
||||||
<span class="nx">prompt</span><span class="p">.</span><span class="nx">allowEmpty</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
|
|
||||||
|
|
||||||
<span class="kd">var</span> <span class="nx">stdin</span><span class="p">,</span> <span class="nx">stdout</span><span class="p">;</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">¶</a> </div> <p>Create an empty object for the properties
|
|
||||||
known to <code>prompt</code></p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">prompt</span><span class="p">.</span><span class="nx">properties</span> <span class="o">=</span> <span class="p">{};</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">¶</a> </div> <p>Setup the default winston logger to use
|
|
||||||
the <code>cli</code> levels and colors.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">logger</span><span class="p">.</span><span class="nx">cli</span><span class="p">();</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">¶</a> </div> <h3>function start (options)</h3>
|
|
||||||
|
|
||||||
<h4>@options {Object} <strong>Optional</strong> Options to consume by prompt</h4>
|
|
||||||
|
|
||||||
<p>Starts the prompt by listening to the appropriate events on <code>options.stdin</code>
|
|
||||||
and <code>options.stdout</code>. If no streams are supplied, then <code>process.stdin</code>
|
|
||||||
and <code>process.stdout</code> are used, respectively.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">prompt</span><span class="p">.</span><span class="nx">start</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">options</span><span class="p">)</span> <span class="p">{</span>
|
|
||||||
<span class="k">if</span> <span class="p">(</span><span class="nx">prompt</span><span class="p">.</span><span class="nx">started</span><span class="p">)</span> <span class="p">{</span>
|
|
||||||
<span class="k">return</span><span class="p">;</span>
|
|
||||||
<span class="p">}</span>
|
|
||||||
|
|
||||||
<span class="nx">options</span> <span class="o">=</span> <span class="nx">options</span> <span class="o">||</span> <span class="p">{};</span>
|
|
||||||
<span class="nx">stdin</span> <span class="o">=</span> <span class="nx">options</span><span class="p">.</span><span class="nx">stdin</span> <span class="o">||</span> <span class="nx">process</span><span class="p">.</span><span class="nx">openStdin</span><span class="p">();</span>
|
|
||||||
<span class="nx">stdout</span> <span class="o">=</span> <span class="nx">options</span><span class="p">.</span><span class="nx">stdout</span> <span class="o">||</span> <span class="nx">process</span><span class="p">.</span><span class="nx">stdout</span><span class="p">;</span>
|
|
||||||
|
|
||||||
<span class="nx">prompt</span><span class="p">.</span><span class="nx">allowEmpty</span> <span class="o">=</span> <span class="nx">options</span><span class="p">.</span><span class="nx">allowEmpty</span> <span class="o">||</span> <span class="kc">false</span><span class="p">;</span>
|
|
||||||
|
|
||||||
<span class="nx">process</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">'SIGINT'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
|
|
||||||
<span class="nx">stdout</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="s1">'\n'</span><span class="p">);</span>
|
|
||||||
<span class="nx">process</span><span class="p">.</span><span class="nx">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
|
|
||||||
<span class="p">})</span>
|
|
||||||
|
|
||||||
<span class="nx">prompt</span><span class="p">.</span><span class="nx">emit</span><span class="p">(</span><span class="s1">'start'</span><span class="p">);</span>
|
|
||||||
<span class="nx">prompt</span><span class="p">.</span><span class="nx">started</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
|
|
||||||
<span class="k">return</span> <span class="nx">prompt</span><span class="p">;</span>
|
|
||||||
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">¶</a> </div> <h3>function pause ()</h3>
|
|
||||||
|
|
||||||
<p>Pauses input coming in from stdin</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">prompt</span><span class="p">.</span><span class="nx">pause</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
|
|
||||||
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">prompt</span><span class="p">.</span><span class="nx">started</span> <span class="o">||</span> <span class="nx">prompt</span><span class="p">.</span><span class="nx">paused</span><span class="p">)</span> <span class="p">{</span>
|
|
||||||
<span class="k">return</span><span class="p">;</span>
|
|
||||||
<span class="p">}</span>
|
|
||||||
|
|
||||||
<span class="nx">stdin</span><span class="p">.</span><span class="nx">pause</span><span class="p">();</span>
|
|
||||||
<span class="nx">prompt</span><span class="p">.</span><span class="nx">emit</span><span class="p">(</span><span class="s1">'pause'</span><span class="p">);</span>
|
|
||||||
<span class="nx">prompt</span><span class="p">.</span><span class="nx">paused</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
|
|
||||||
<span class="k">return</span> <span class="nx">prompt</span><span class="p">;</span>
|
|
||||||
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">¶</a> </div> <h3>function resume ()</h3>
|
|
||||||
|
|
||||||
<p>Resumes input coming in from stdin </p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">prompt</span><span class="p">.</span><span class="nx">resume</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
|
|
||||||
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">prompt</span><span class="p">.</span><span class="nx">started</span> <span class="o">||</span> <span class="o">!</span><span class="nx">prompt</span><span class="p">.</span><span class="nx">paused</span><span class="p">)</span> <span class="p">{</span>
|
|
||||||
<span class="k">return</span><span class="p">;</span>
|
|
||||||
<span class="p">}</span>
|
|
||||||
|
|
||||||
<span class="nx">stdin</span><span class="p">.</span><span class="nx">resume</span><span class="p">();</span>
|
|
||||||
<span class="nx">prompt</span><span class="p">.</span><span class="nx">emit</span><span class="p">(</span><span class="s1">'resume'</span><span class="p">);</span>
|
|
||||||
<span class="nx">prompt</span><span class="p">.</span><span class="nx">paused</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
|
|
||||||
<span class="k">return</span> <span class="nx">prompt</span><span class="p">;</span>
|
|
||||||
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">¶</a> </div> <h3>function get (msg, [validator,] callback)</h3>
|
|
||||||
|
|
||||||
<h4>@msg {Array|Object|string} Set of variables to get input for.</h4>
|
|
||||||
|
|
||||||
<h4>@callback {function} Continuation to pass control to when complete.</h4>
|
|
||||||
|
|
||||||
<p>Gets input from the user via stdin for the specified message(s) <code>msg</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">prompt</span><span class="p">.</span><span class="nx">get</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">msg</span><span class="p">,</span> <span class="nx">callback</span><span class="p">)</span> <span class="p">{</span>
|
|
||||||
<span class="kd">var</span> <span class="nx">vars</span> <span class="o">=</span> <span class="o">!</span><span class="nb">Array</span><span class="p">.</span><span class="nx">isArray</span><span class="p">(</span><span class="nx">msg</span><span class="p">)</span> <span class="o">?</span> <span class="p">[</span><span class="nx">msg</span><span class="p">]</span> <span class="o">:</span> <span class="nx">msg</span><span class="p">,</span>
|
|
||||||
<span class="nx">result</span> <span class="o">=</span> <span class="p">{};</span>
|
|
||||||
|
|
||||||
<span class="nx">vars</span> <span class="o">=</span> <span class="nx">vars</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="kd">function</span> <span class="p">(</span><span class="nx">v</span><span class="p">)</span> <span class="p">{</span>
|
|
||||||
<span class="k">if</span> <span class="p">(</span><span class="k">typeof</span> <span class="nx">v</span> <span class="o">===</span> <span class="s1">'string'</span><span class="p">)</span> <span class="p">{</span>
|
|
||||||
<span class="nx">v</span> <span class="o">=</span> <span class="nx">v</span><span class="p">.</span><span class="nx">toLowerCase</span><span class="p">();</span>
|
|
||||||
<span class="p">}</span>
|
|
||||||
|
|
||||||
<span class="k">return</span> <span class="nx">prompt</span><span class="p">.</span><span class="nx">properties</span><span class="p">[</span><span class="nx">v</span><span class="p">]</span> <span class="o">||</span> <span class="nx">v</span><span class="p">;</span>
|
|
||||||
<span class="p">});</span>
|
|
||||||
|
|
||||||
<span class="kd">function</span> <span class="nx">get</span><span class="p">(</span><span class="nx">target</span><span class="p">,</span> <span class="nx">next</span><span class="p">)</span> <span class="p">{</span>
|
|
||||||
<span class="nx">prompt</span><span class="p">.</span><span class="nx">getInput</span><span class="p">(</span><span class="nx">target</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">line</span><span class="p">)</span> <span class="p">{</span>
|
|
||||||
<span class="k">if</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
|
|
||||||
<span class="k">return</span> <span class="nx">next</span><span class="p">(</span><span class="nx">err</span><span class="p">);</span>
|
|
||||||
<span class="p">}</span>
|
|
||||||
|
|
||||||
<span class="kd">var</span> <span class="nx">name</span> <span class="o">=</span> <span class="nx">target</span><span class="p">.</span><span class="nx">name</span> <span class="o">||</span> <span class="nx">target</span><span class="p">;</span>
|
|
||||||
<span class="nx">result</span><span class="p">[</span><span class="nx">name</span><span class="p">]</span> <span class="o">=</span> <span class="nx">line</span><span class="p">;</span>
|
|
||||||
<span class="nx">next</span><span class="p">();</span>
|
|
||||||
<span class="p">});</span>
|
|
||||||
<span class="p">}</span>
|
|
||||||
|
|
||||||
<span class="nx">async</span><span class="p">.</span><span class="nx">forEachSeries</span><span class="p">(</span><span class="nx">vars</span><span class="p">,</span> <span class="nx">get</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
|
|
||||||
<span class="k">return</span> <span class="nx">err</span> <span class="o">?</span> <span class="nx">callback</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="o">:</span> <span class="nx">callback</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="nx">result</span><span class="p">);</span>
|
|
||||||
<span class="p">});</span>
|
|
||||||
|
|
||||||
<span class="k">return</span> <span class="nx">prompt</span><span class="p">;</span>
|
|
||||||
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">¶</a> </div> <h3>function getInput (msg, validator, callback)</h3>
|
|
||||||
|
|
||||||
<h4>@msg {Object|string} Variable to get input for.</h4>
|
|
||||||
|
|
||||||
<h4>@callback {function} Continuation to pass control to when complete.</h4>
|
|
||||||
|
|
||||||
<p>Gets input from the user via stdin for the specified message <code>msg</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">prompt</span><span class="p">.</span><span class="nx">getInput</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">prop</span><span class="p">,</span> <span class="nx">callback</span><span class="p">)</span> <span class="p">{</span>
|
|
||||||
<span class="kd">var</span> <span class="nx">name</span> <span class="o">=</span> <span class="nx">prop</span><span class="p">.</span><span class="nx">message</span> <span class="o">||</span> <span class="nx">prop</span><span class="p">.</span><span class="nx">name</span> <span class="o">||</span> <span class="nx">prop</span><span class="p">,</span>
|
|
||||||
<span class="nx">raw</span> <span class="o">=</span> <span class="p">[</span><span class="s1">'prompt'</span><span class="p">,</span> <span class="s1">': '</span> <span class="o">+</span> <span class="nx">name</span><span class="p">.</span><span class="nx">grey</span><span class="p">,</span> <span class="s1">': '</span><span class="p">.</span><span class="nx">grey</span><span class="p">],</span>
|
|
||||||
<span class="nx">read</span> <span class="o">=</span> <span class="nx">prop</span><span class="p">.</span><span class="nx">hidden</span> <span class="o">?</span> <span class="nx">prompt</span><span class="p">.</span><span class="nx">readLineHidden</span> <span class="o">:</span> <span class="nx">prompt</span><span class="p">.</span><span class="nx">readLine</span><span class="p">,</span>
|
|
||||||
<span class="nx">length</span><span class="p">,</span> <span class="nx">msg</span><span class="p">;</span>
|
|
||||||
|
|
||||||
<span class="k">if</span> <span class="p">(</span><span class="nx">prop</span><span class="p">.</span><span class="k">default</span><span class="p">)</span> <span class="p">{</span>
|
|
||||||
<span class="nx">raw</span><span class="p">.</span><span class="nx">splice</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="s1">' ('</span> <span class="o">+</span> <span class="nx">prop</span><span class="p">.</span><span class="k">default</span> <span class="o">+</span> <span class="s1">')'</span><span class="p">);</span>
|
|
||||||
<span class="p">}</span>
|
|
||||||
</pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">¶</a> </div> <p>Calculate the raw length and colorize the prompt</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">length</span> <span class="o">=</span> <span class="nx">raw</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="s1">''</span><span class="p">).</span><span class="nx">length</span><span class="p">;</span>
|
|
||||||
<span class="nx">raw</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="nx">raw</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
|
|
||||||
<span class="nx">msg</span> <span class="o">=</span> <span class="nx">raw</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="s1">''</span><span class="p">);</span>
|
|
||||||
|
|
||||||
<span class="k">if</span> <span class="p">(</span><span class="nx">prop</span><span class="p">.</span><span class="nx">help</span><span class="p">)</span> <span class="p">{</span>
|
|
||||||
<span class="nx">prop</span><span class="p">.</span><span class="nx">help</span><span class="p">.</span><span class="nx">forEach</span><span class="p">(</span><span class="kd">function</span> <span class="p">(</span><span class="nx">line</span><span class="p">)</span> <span class="p">{</span>
|
|
||||||
<span class="nx">logger</span><span class="p">.</span><span class="nx">help</span><span class="p">(</span><span class="nx">line</span><span class="p">);</span>
|
|
||||||
<span class="p">});</span>
|
|
||||||
<span class="p">}</span>
|
|
||||||
|
|
||||||
<span class="nx">stdout</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="nx">msg</span><span class="p">);</span>
|
|
||||||
<span class="nx">prompt</span><span class="p">.</span><span class="nx">emit</span><span class="p">(</span><span class="s1">'prompt'</span><span class="p">,</span> <span class="nx">prop</span><span class="p">);</span>
|
|
||||||
|
|
||||||
<span class="nx">read</span><span class="p">.</span><span class="nx">call</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">line</span><span class="p">)</span> <span class="p">{</span>
|
|
||||||
<span class="k">if</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
|
|
||||||
<span class="k">return</span> <span class="nx">callback</span><span class="p">(</span><span class="nx">err</span><span class="p">);</span>
|
|
||||||
<span class="p">}</span>
|
|
||||||
|
|
||||||
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">line</span> <span class="o">||</span> <span class="nx">line</span> <span class="o">===</span> <span class="s1">''</span><span class="p">)</span> <span class="p">{</span>
|
|
||||||
<span class="nx">line</span> <span class="o">=</span> <span class="nx">prop</span><span class="p">.</span><span class="k">default</span> <span class="o">||</span> <span class="nx">line</span><span class="p">;</span>
|
|
||||||
<span class="p">}</span>
|
|
||||||
|
|
||||||
<span class="k">if</span> <span class="p">(</span><span class="nx">prop</span><span class="p">.</span><span class="nx">validator</span> <span class="o">||</span> <span class="nx">prop</span><span class="p">.</span><span class="nx">empty</span> <span class="o">===</span> <span class="kc">false</span><span class="p">)</span> <span class="p">{</span>
|
|
||||||
<span class="kd">var</span> <span class="nx">valid</span><span class="p">;</span>
|
|
||||||
|
|
||||||
<span class="k">if</span> <span class="p">(</span><span class="nx">prop</span><span class="p">.</span><span class="nx">validator</span><span class="p">)</span> <span class="p">{</span>
|
|
||||||
<span class="nx">valid</span> <span class="o">=</span> <span class="nx">prop</span><span class="p">.</span><span class="nx">validator</span><span class="p">.</span><span class="nx">test</span>
|
|
||||||
<span class="o">?</span> <span class="nx">prop</span><span class="p">.</span><span class="nx">validator</span><span class="p">.</span><span class="nx">test</span><span class="p">(</span><span class="nx">line</span><span class="p">)</span>
|
|
||||||
<span class="o">:</span> <span class="nx">prop</span><span class="p">.</span><span class="nx">validator</span><span class="p">(</span><span class="nx">line</span><span class="p">);</span>
|
|
||||||
<span class="p">}</span>
|
|
||||||
|
|
||||||
<span class="k">if</span> <span class="p">(</span><span class="nx">prop</span><span class="p">.</span><span class="nx">empty</span> <span class="o">===</span> <span class="kc">false</span> <span class="o">&&</span> <span class="nx">valid</span><span class="p">)</span> <span class="p">{</span>
|
|
||||||
<span class="nx">valid</span> <span class="o">=</span> <span class="nx">line</span><span class="p">.</span><span class="nx">length</span> <span class="o">></span> <span class="mi">0</span><span class="p">;</span>
|
|
||||||
<span class="nx">prop</span><span class="p">.</span><span class="nx">warning</span> <span class="o">=</span> <span class="nx">prop</span><span class="p">.</span><span class="nx">warning</span> <span class="o">||</span> <span class="s1">'You must supply a value.'</span><span class="p">;</span>
|
|
||||||
<span class="p">}</span>
|
|
||||||
|
|
||||||
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">valid</span><span class="p">)</span> <span class="p">{</span>
|
|
||||||
<span class="nx">logger</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="s1">'Invalid input for '</span> <span class="o">+</span> <span class="nx">name</span><span class="p">.</span><span class="nx">grey</span><span class="p">);</span>
|
|
||||||
<span class="k">if</span> <span class="p">(</span><span class="nx">prop</span><span class="p">.</span><span class="nx">warning</span><span class="p">)</span> <span class="p">{</span>
|
|
||||||
<span class="nx">logger</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="nx">prop</span><span class="p">.</span><span class="nx">warning</span><span class="p">);</span>
|
|
||||||
<span class="p">}</span>
|
|
||||||
|
|
||||||
<span class="nx">prompt</span><span class="p">.</span><span class="nx">emit</span><span class="p">(</span><span class="s1">'invalid'</span><span class="p">,</span> <span class="nx">prop</span><span class="p">,</span> <span class="nx">line</span><span class="p">);</span>
|
|
||||||
<span class="k">return</span> <span class="nx">prompt</span><span class="p">.</span><span class="nx">getInput</span><span class="p">(</span><span class="nx">prop</span><span class="p">,</span> <span class="nx">callback</span><span class="p">);</span>
|
|
||||||
<span class="p">}</span>
|
|
||||||
<span class="p">}</span>
|
|
||||||
|
|
||||||
<span class="nx">logger</span><span class="p">.</span><span class="nx">input</span><span class="p">(</span><span class="nx">line</span><span class="p">.</span><span class="nx">yellow</span><span class="p">);</span>
|
|
||||||
<span class="nx">callback</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="nx">line</span><span class="p">);</span>
|
|
||||||
<span class="p">});</span>
|
|
||||||
|
|
||||||
<span class="k">return</span> <span class="nx">prompt</span><span class="p">;</span>
|
|
||||||
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">¶</a> </div> <h3>function addProperties (obj, properties, callback)</h3>
|
|
||||||
|
|
||||||
<h4>@obj {Object} Object to add properties to</h4>
|
|
||||||
|
|
||||||
<h4>@properties {Array} List of properties to get values for</h4>
|
|
||||||
|
|
||||||
<h4>@callback {function} Continuation to pass control to when complete.</h4>
|
|
||||||
|
|
||||||
<p>Prompts the user for values each of the <code>properties</code> if <code>obj</code> does not already
|
|
||||||
have a value for the property. Responds with the modified object. </p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">prompt</span><span class="p">.</span><span class="nx">addProperties</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">obj</span><span class="p">,</span> <span class="nx">properties</span><span class="p">,</span> <span class="nx">callback</span><span class="p">)</span> <span class="p">{</span>
|
|
||||||
<span class="nx">properties</span> <span class="o">=</span> <span class="nx">properties</span><span class="p">.</span><span class="nx">filter</span><span class="p">(</span><span class="kd">function</span> <span class="p">(</span><span class="nx">prop</span><span class="p">)</span> <span class="p">{</span>
|
|
||||||
<span class="k">return</span> <span class="k">typeof</span> <span class="nx">obj</span><span class="p">[</span><span class="nx">prop</span><span class="p">]</span> <span class="o">===</span> <span class="s1">'undefined'</span><span class="p">;</span>
|
|
||||||
<span class="p">});</span>
|
|
||||||
|
|
||||||
<span class="k">if</span> <span class="p">(</span><span class="nx">properties</span><span class="p">.</span><span class="nx">length</span> <span class="o">===</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
|
|
||||||
<span class="k">return</span> <span class="nx">callback</span><span class="p">(</span><span class="nx">obj</span><span class="p">);</span>
|
|
||||||
<span class="p">}</span>
|
|
||||||
|
|
||||||
<span class="nx">prompt</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="nx">properties</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">results</span><span class="p">)</span> <span class="p">{</span>
|
|
||||||
<span class="k">if</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
|
|
||||||
<span class="k">return</span> <span class="nx">callback</span><span class="p">(</span><span class="nx">err</span><span class="p">);</span>
|
|
||||||
<span class="p">}</span>
|
|
||||||
<span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">results</span><span class="p">)</span> <span class="p">{</span>
|
|
||||||
<span class="k">return</span> <span class="nx">callback</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="nx">obj</span><span class="p">);</span>
|
|
||||||
<span class="p">}</span>
|
|
||||||
|
|
||||||
<span class="kd">function</span> <span class="nx">putNested</span> <span class="p">(</span><span class="nx">obj</span><span class="p">,</span> <span class="nx">path</span><span class="p">,</span> <span class="nx">value</span><span class="p">)</span> <span class="p">{</span>
|
|
||||||
<span class="kd">var</span> <span class="nx">last</span> <span class="o">=</span> <span class="nx">obj</span><span class="p">,</span> <span class="nx">key</span><span class="p">;</span>
|
|
||||||
|
|
||||||
<span class="k">while</span> <span class="p">(</span><span class="nx">path</span><span class="p">.</span><span class="nx">length</span> <span class="o">></span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
|
|
||||||
<span class="nx">key</span> <span class="o">=</span> <span class="nx">path</span><span class="p">.</span><span class="nx">shift</span><span class="p">();</span>
|
|
||||||
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">last</span><span class="p">[</span><span class="nx">key</span><span class="p">])</span> <span class="p">{</span>
|
|
||||||
<span class="nx">last</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span> <span class="o">=</span> <span class="p">{};</span>
|
|
||||||
<span class="p">}</span>
|
|
||||||
|
|
||||||
<span class="nx">last</span> <span class="o">=</span> <span class="nx">last</span><span class="p">[</span><span class="nx">key</span><span class="p">];</span>
|
|
||||||
<span class="p">}</span>
|
|
||||||
|
|
||||||
<span class="nx">last</span><span class="p">[</span><span class="nx">path</span><span class="p">.</span><span class="nx">shift</span><span class="p">()]</span> <span class="o">=</span> <span class="nx">value</span><span class="p">;</span>
|
|
||||||
<span class="p">}</span>
|
|
||||||
|
|
||||||
<span class="nb">Object</span><span class="p">.</span><span class="nx">keys</span><span class="p">(</span><span class="nx">results</span><span class="p">).</span><span class="nx">forEach</span><span class="p">(</span><span class="kd">function</span> <span class="p">(</span><span class="nx">key</span><span class="p">)</span> <span class="p">{</span>
|
|
||||||
<span class="nx">putNested</span><span class="p">(</span><span class="nx">obj</span><span class="p">,</span> <span class="nx">key</span><span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="s1">'.'</span><span class="p">),</span> <span class="nx">results</span><span class="p">[</span><span class="nx">key</span><span class="p">]);</span>
|
|
||||||
<span class="p">});</span>
|
|
||||||
|
|
||||||
<span class="nx">callback</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="nx">obj</span><span class="p">);</span>
|
|
||||||
<span class="p">});</span>
|
|
||||||
|
|
||||||
<span class="k">return</span> <span class="nx">prompt</span><span class="p">;</span>
|
|
||||||
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-12">¶</a> </div> <h3>function readLine (callback)</h3>
|
|
||||||
|
|
||||||
<h4>@callback {function} Continuation to respond to when complete</h4>
|
|
||||||
|
|
||||||
<p>Gets a single line of input from the user. </p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">prompt</span><span class="p">.</span><span class="nx">readLine</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">callback</span><span class="p">)</span> <span class="p">{</span>
|
|
||||||
<span class="kd">var</span> <span class="nx">value</span> <span class="o">=</span> <span class="s1">''</span><span class="p">,</span> <span class="nx">buffer</span> <span class="o">=</span> <span class="s1">''</span><span class="p">;</span>
|
|
||||||
<span class="nx">prompt</span><span class="p">.</span><span class="nx">resume</span><span class="p">();</span>
|
|
||||||
<span class="nx">stdin</span><span class="p">.</span><span class="nx">setEncoding</span><span class="p">(</span><span class="s1">'utf8'</span><span class="p">);</span>
|
|
||||||
<span class="nx">stdin</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">'error'</span><span class="p">,</span> <span class="nx">callback</span><span class="p">);</span>
|
|
||||||
<span class="nx">stdin</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">'data'</span><span class="p">,</span> <span class="kd">function</span> <span class="nx">data</span> <span class="p">(</span><span class="nx">chunk</span><span class="p">)</span> <span class="p">{</span>
|
|
||||||
<span class="nx">value</span> <span class="o">+=</span> <span class="nx">buffer</span> <span class="o">+</span> <span class="nx">chunk</span><span class="p">;</span>
|
|
||||||
<span class="nx">buffer</span> <span class="o">=</span> <span class="s1">''</span><span class="p">;</span>
|
|
||||||
<span class="nx">value</span> <span class="o">=</span> <span class="nx">value</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/\r/g</span><span class="p">,</span> <span class="s1">''</span><span class="p">);</span>
|
|
||||||
<span class="k">if</span> <span class="p">(</span><span class="nx">value</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="s1">'\n'</span><span class="p">)</span> <span class="o">!==</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
|
|
||||||
<span class="k">if</span> <span class="p">(</span><span class="nx">value</span> <span class="o">!==</span> <span class="s1">'\n'</span><span class="p">)</span> <span class="p">{</span>
|
|
||||||
<span class="nx">value</span> <span class="o">=</span> <span class="nx">value</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/^\n+/</span><span class="p">,</span> <span class="s1">''</span><span class="p">);</span>
|
|
||||||
<span class="p">}</span>
|
|
||||||
|
|
||||||
<span class="nx">buffer</span> <span class="o">=</span> <span class="nx">value</span><span class="p">.</span><span class="nx">substr</span><span class="p">(</span><span class="nx">value</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="s1">'\n'</span><span class="p">));</span>
|
|
||||||
<span class="nx">val</span> <span class="o">=</span> <span class="nx">value</span><span class="p">.</span><span class="nx">substr</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nx">value</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="s1">'\n'</span><span class="p">));</span>
|
|
||||||
<span class="nx">prompt</span><span class="p">.</span><span class="nx">pause</span><span class="p">();</span>
|
|
||||||
<span class="nx">stdin</span><span class="p">.</span><span class="nx">removeListener</span><span class="p">(</span><span class="s1">'data'</span><span class="p">,</span> <span class="nx">data</span><span class="p">);</span>
|
|
||||||
<span class="nx">stdin</span><span class="p">.</span><span class="nx">removeListener</span><span class="p">(</span><span class="s1">'error'</span><span class="p">,</span> <span class="nx">callback</span><span class="p">);</span>
|
|
||||||
<span class="nx">value</span> <span class="o">=</span> <span class="nx">value</span><span class="p">.</span><span class="nx">trim</span><span class="p">();</span>
|
|
||||||
<span class="nx">callback</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="nx">value</span><span class="p">);</span>
|
|
||||||
<span class="p">}</span>
|
|
||||||
<span class="p">});</span>
|
|
||||||
|
|
||||||
<span class="k">return</span> <span class="nx">prompt</span><span class="p">;</span>
|
|
||||||
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-13">¶</a> </div> <h3>function readLineHidden (callback)</h3>
|
|
||||||
|
|
||||||
<h4>@callback {function} Continuation to respond to when complete</h4>
|
|
||||||
|
|
||||||
<p>Gets a single line of hidden input (i.e. <code>rawMode = true</code>) from the user. </p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">prompt</span><span class="p">.</span><span class="nx">readLineHidden</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">callback</span><span class="p">)</span> <span class="p">{</span>
|
|
||||||
<span class="kd">var</span> <span class="nx">value</span> <span class="o">=</span> <span class="s1">''</span><span class="p">,</span> <span class="nx">buffer</span> <span class="o">=</span> <span class="s1">''</span><span class="p">;</span>
|
|
||||||
<span class="nx">stdio</span><span class="p">.</span><span class="nx">setRawMode</span><span class="p">(</span><span class="kc">true</span><span class="p">);</span>
|
|
||||||
<span class="nx">prompt</span><span class="p">.</span><span class="nx">resume</span><span class="p">();</span>
|
|
||||||
<span class="nx">stdin</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">'error'</span><span class="p">,</span> <span class="nx">callback</span><span class="p">);</span>
|
|
||||||
<span class="nx">stdin</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">'data'</span><span class="p">,</span> <span class="kd">function</span> <span class="nx">data</span> <span class="p">(</span><span class="nx">c</span><span class="p">)</span> <span class="p">{</span>
|
|
||||||
<span class="nx">c</span> <span class="o">=</span> <span class="s1">''</span> <span class="o">+</span> <span class="nx">c</span><span class="p">;</span>
|
|
||||||
<span class="k">switch</span> <span class="p">(</span><span class="nx">c</span><span class="p">)</span> <span class="p">{</span>
|
|
||||||
<span class="k">case</span> <span class="s1">'\n'</span><span class="o">:</span> <span class="k">case</span> <span class="s1">'\r'</span><span class="o">:</span> <span class="k">case</span> <span class="s1">'\r\n'</span><span class="o">:</span> <span class="k">case</span> <span class="s1">'\u0004'</span><span class="o">:</span>
|
|
||||||
<span class="nx">stdio</span><span class="p">.</span><span class="nx">setRawMode</span><span class="p">(</span><span class="kc">false</span><span class="p">);</span>
|
|
||||||
<span class="nx">stdin</span><span class="p">.</span><span class="nx">removeListener</span><span class="p">(</span><span class="s1">'data'</span><span class="p">,</span> <span class="nx">data</span><span class="p">);</span>
|
|
||||||
<span class="nx">stdin</span><span class="p">.</span><span class="nx">removeListener</span><span class="p">(</span><span class="s1">'error'</span><span class="p">,</span> <span class="nx">callback</span><span class="p">);</span>
|
|
||||||
<span class="nx">value</span> <span class="o">=</span> <span class="nx">value</span><span class="p">.</span><span class="nx">trim</span><span class="p">();</span>
|
|
||||||
<span class="nx">stdout</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="s1">'\n'</span><span class="p">);</span>
|
|
||||||
<span class="nx">stdout</span><span class="p">.</span><span class="nx">flush</span><span class="p">();</span>
|
|
||||||
<span class="nx">prompt</span><span class="p">.</span><span class="nx">pause</span><span class="p">();</span>
|
|
||||||
<span class="k">return</span> <span class="nx">callback</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="nx">value</span><span class="p">)</span>
|
|
||||||
<span class="k">case</span> <span class="s1">'\u0003'</span><span class="o">:</span> <span class="k">case</span> <span class="s1">'\0'</span><span class="o">:</span>
|
|
||||||
<span class="nx">stdout</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="s1">'\n'</span><span class="p">);</span>
|
|
||||||
<span class="nx">process</span><span class="p">.</span><span class="nx">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
|
|
||||||
<span class="k">break</span><span class="p">;</span>
|
|
||||||
<span class="k">default</span><span class="o">:</span>
|
|
||||||
<span class="nx">value</span> <span class="o">+=</span> <span class="nx">buffer</span> <span class="o">+</span> <span class="nx">c</span>
|
|
||||||
<span class="nx">buffer</span> <span class="o">=</span> <span class="s1">''</span><span class="p">;</span>
|
|
||||||
<span class="k">break</span><span class="p">;</span>
|
|
||||||
<span class="p">}</span>
|
|
||||||
<span class="p">});</span>
|
|
||||||
|
|
||||||
<span class="k">return</span> <span class="nx">prompt</span><span class="p">;</span>
|
|
||||||
<span class="p">};</span>
|
|
||||||
|
|
||||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
|
@ -1,35 +0,0 @@
|
|||||||
/*
|
|
||||||
* add-properties.js: Example of how to add properties to an object using prompt.
|
|
||||||
*
|
|
||||||
* (C) 2010, Nodejitsu Inc.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
var prompt = require('../lib/prompt');
|
|
||||||
|
|
||||||
//
|
|
||||||
// Start the prompt
|
|
||||||
//
|
|
||||||
prompt.start();
|
|
||||||
|
|
||||||
var obj = {
|
|
||||||
password: 'lamepassword',
|
|
||||||
mindset: 'NY'
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Log the initial object.
|
|
||||||
//
|
|
||||||
console.log('Initial object to be extended:');
|
|
||||||
console.dir(obj);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Add two properties to the empty object: username and email
|
|
||||||
//
|
|
||||||
prompt.addProperties(obj, ['username', 'email'], function (err) {
|
|
||||||
//
|
|
||||||
// Log the results.
|
|
||||||
//
|
|
||||||
console.log('Updated object received:');
|
|
||||||
console.dir(obj);
|
|
||||||
});
|
|
@ -1,35 +0,0 @@
|
|||||||
/*
|
|
||||||
* existing-properties.js: Example of using prompt with predefined properties.
|
|
||||||
*
|
|
||||||
* (C) 2010, Nodejitsu Inc.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
var prompt = require('../lib/prompt');
|
|
||||||
|
|
||||||
prompt.properties = {
|
|
||||||
email: {
|
|
||||||
format: 'email',
|
|
||||||
message: 'Must be a valid email address'
|
|
||||||
},
|
|
||||||
password: {
|
|
||||||
hidden: true
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// Start the prompt
|
|
||||||
//
|
|
||||||
prompt.start();
|
|
||||||
|
|
||||||
//
|
|
||||||
// Get two properties from the user: email, password
|
|
||||||
//
|
|
||||||
prompt.get(['email', 'password'], function (err, result) {
|
|
||||||
//
|
|
||||||
// Log the results.
|
|
||||||
//
|
|
||||||
console.log('Command-line input received:');
|
|
||||||
console.log(' email: ' + result.email);
|
|
||||||
console.log(' password: ' + result.password);
|
|
||||||
});
|
|
@ -1,44 +0,0 @@
|
|||||||
/*
|
|
||||||
* history.js: Example of using the prompt history capabilities.
|
|
||||||
*
|
|
||||||
* (C) 2010, Nodejitsu Inc.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
var prompt = require('../lib/prompt');
|
|
||||||
|
|
||||||
//
|
|
||||||
// Start the prompt
|
|
||||||
//
|
|
||||||
prompt.start();
|
|
||||||
|
|
||||||
var properties = {
|
|
||||||
properties: {
|
|
||||||
animal: {
|
|
||||||
description: 'Enter an animal',
|
|
||||||
default: 'dog',
|
|
||||||
pattern: /dog|cat/
|
|
||||||
},
|
|
||||||
sound: {
|
|
||||||
description: 'What sound does this animal make?',
|
|
||||||
conform: function (value) {
|
|
||||||
var animal = prompt.history(0).value;
|
|
||||||
|
|
||||||
return animal === 'dog' && value === 'woof'
|
|
||||||
|| animal === 'cat' && value === 'meow';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Get two properties from the user
|
|
||||||
//
|
|
||||||
prompt.get(properties, function (err, result) {
|
|
||||||
//
|
|
||||||
// Log the results.
|
|
||||||
//
|
|
||||||
console.log('Command-line input received:');
|
|
||||||
console.log(' animal: ' + result.animal);
|
|
||||||
console.log(' sound: ' + result.sound);
|
|
||||||
});
|
|
@ -1,37 +0,0 @@
|
|||||||
/*
|
|
||||||
* property-prompt.js: Example of using prompt with complex properties.
|
|
||||||
*
|
|
||||||
* (C) 2010, Nodejitsu Inc.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
var prompt = require('../lib/prompt');
|
|
||||||
|
|
||||||
var schema = {
|
|
||||||
properties: {
|
|
||||||
url: {
|
|
||||||
required: true,
|
|
||||||
format: 'url'
|
|
||||||
},
|
|
||||||
auth: {
|
|
||||||
properties: {
|
|
||||||
username: {
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
password: {
|
|
||||||
required: true,
|
|
||||||
hidden: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
prompt.start();
|
|
||||||
|
|
||||||
prompt.get(schema, function (err, result) {
|
|
||||||
console.log('Command-line input received:');
|
|
||||||
console.log(' url: ' + result.url);
|
|
||||||
console.log(' auth:username: ' + result.auth.username);
|
|
||||||
console.log(' auth:password: ' + result.auth.password);
|
|
||||||
});
|
|
@ -1,36 +0,0 @@
|
|||||||
/*
|
|
||||||
* simple-prompt.js: Simple example of using prompt.
|
|
||||||
*
|
|
||||||
* (C) 2010, Nodejitsu Inc.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
var prompt = require('../lib/prompt');
|
|
||||||
|
|
||||||
//
|
|
||||||
// Start the prompt
|
|
||||||
//
|
|
||||||
prompt.start();
|
|
||||||
|
|
||||||
//
|
|
||||||
// Get two properties from the user: username and email
|
|
||||||
//
|
|
||||||
prompt.get([
|
|
||||||
{
|
|
||||||
name: 'username',
|
|
||||||
validator: /^[a-z]+$/,
|
|
||||||
warning: 'Username should consist only lowercase alphabets',
|
|
||||||
empty: false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'email',
|
|
||||||
message: 'Email Address'
|
|
||||||
}
|
|
||||||
], function (err, result) {
|
|
||||||
//
|
|
||||||
// Log the results.
|
|
||||||
//
|
|
||||||
console.log('Command-line input received:');
|
|
||||||
console.log(' username: ' + result.username);
|
|
||||||
console.log(' email: ' + result.email);
|
|
||||||
});
|
|
@ -1,52 +0,0 @@
|
|||||||
/*
|
|
||||||
* override-validation.js: Example of using prompt with complex properties and command-line input.
|
|
||||||
*
|
|
||||||
* (C) 2010, Nodejitsu Inc.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
var prompt = require('../lib/prompt'),
|
|
||||||
optimist = require('optimist');
|
|
||||||
|
|
||||||
var schema = {
|
|
||||||
properties: {
|
|
||||||
name: {
|
|
||||||
pattern: /^[a-zA-Z\s-]+$/,
|
|
||||||
message: 'Name must be only letters, spaces, or dashes',
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
email: {
|
|
||||||
name: 'email',
|
|
||||||
format: 'email',
|
|
||||||
message: 'Must be a valid email address'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// Set the overrides
|
|
||||||
//
|
|
||||||
prompt.override = optimist.argv
|
|
||||||
|
|
||||||
//
|
|
||||||
// Start the prompt
|
|
||||||
//
|
|
||||||
prompt.start();
|
|
||||||
|
|
||||||
//
|
|
||||||
// Get two properties from the user: email, password
|
|
||||||
//
|
|
||||||
prompt.get(schema, function (err, result) {
|
|
||||||
//
|
|
||||||
// Log the results.
|
|
||||||
//
|
|
||||||
console.log('Command-line input received:');
|
|
||||||
console.log(' name: ' + result.name);
|
|
||||||
console.log(' email: ' + result.email);
|
|
||||||
});
|
|
||||||
|
|
||||||
// try running
|
|
||||||
// $ node ./override-validation.js --name USER --email EMAIL
|
|
||||||
// You will only be asked for email becasue it's invalid
|
|
||||||
// $ node ./override-validation.js --name h$acker --email me@example.com
|
|
||||||
// You will only be asked for email becasue it's invalid
|
|
@ -1,34 +0,0 @@
|
|||||||
/*
|
|
||||||
* password.js: Simple example of using prompt.
|
|
||||||
*
|
|
||||||
* (C) 2010, Nodejitsu Inc.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
var prompt = require('../lib/prompt');
|
|
||||||
|
|
||||||
//
|
|
||||||
// Start the prompt
|
|
||||||
//
|
|
||||||
prompt.start();
|
|
||||||
|
|
||||||
//
|
|
||||||
// Get two properties from the user: username and password
|
|
||||||
//
|
|
||||||
prompt.get([{
|
|
||||||
name: 'username',
|
|
||||||
required: true
|
|
||||||
}, {
|
|
||||||
name: 'password',
|
|
||||||
hidden: true,
|
|
||||||
conform: function (value) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}], function (err, result) {
|
|
||||||
//
|
|
||||||
// Log the results.
|
|
||||||
//
|
|
||||||
console.log('Command-line input received:');
|
|
||||||
console.log(' username: ' + result.username);
|
|
||||||
console.log(' password: ' + result.password);
|
|
||||||
});
|
|
@ -1,36 +0,0 @@
|
|||||||
var prompt = require('../lib/prompt'),
|
|
||||||
optimist;
|
|
||||||
|
|
||||||
try {
|
|
||||||
optimist = require('optimist');
|
|
||||||
} catch (err) {
|
|
||||||
throw new Error([
|
|
||||||
'You need to install optimist before this example will work!',
|
|
||||||
'Try: `npm install optimist`.'
|
|
||||||
].join('\n'));
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Set the overrides
|
|
||||||
//
|
|
||||||
prompt.override = optimist.argv
|
|
||||||
|
|
||||||
//
|
|
||||||
// Start the prompt
|
|
||||||
//
|
|
||||||
prompt.start();
|
|
||||||
|
|
||||||
//
|
|
||||||
// Get two properties from the user: username and email
|
|
||||||
//
|
|
||||||
prompt.get(['username', 'email'], function (err, result) {
|
|
||||||
//
|
|
||||||
// Log the results.
|
|
||||||
//
|
|
||||||
console.log('Command-line input received:');
|
|
||||||
console.log(' username: ' + result.username);
|
|
||||||
console.log(' email: ' + result.email);
|
|
||||||
prompt.pause();
|
|
||||||
})
|
|
||||||
|
|
||||||
// $ node ./prompt-override.js --username USER --email EMAIL
|
|
@ -1,45 +0,0 @@
|
|||||||
/*
|
|
||||||
* property-prompt.js: Example of using prompt with complex properties.
|
|
||||||
*
|
|
||||||
* (C) 2010, Nodejitsu Inc.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
var prompt = require('../lib/prompt');
|
|
||||||
|
|
||||||
var schema = {
|
|
||||||
properties: {
|
|
||||||
name: {
|
|
||||||
pattern: /^[a-zA-Z\s-]+$/,
|
|
||||||
message: 'Name must be only letters, spaces, or dashes',
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
email: {
|
|
||||||
name: 'email',
|
|
||||||
format: 'email',
|
|
||||||
message: 'Must be a valid email address'
|
|
||||||
},
|
|
||||||
password: {
|
|
||||||
required: true,
|
|
||||||
hidden: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// Start the prompt
|
|
||||||
//
|
|
||||||
prompt.start();
|
|
||||||
|
|
||||||
//
|
|
||||||
// Get two properties from the user: email, password
|
|
||||||
//
|
|
||||||
prompt.get(schema, function (err, result) {
|
|
||||||
//
|
|
||||||
// Log the results.
|
|
||||||
//
|
|
||||||
console.log('Command-line input received:');
|
|
||||||
console.log(' name: ' + result.name);
|
|
||||||
console.log(' email: ' + result.email);
|
|
||||||
console.log(' password: ' + result.password);
|
|
||||||
});
|
|
@ -1,25 +0,0 @@
|
|||||||
/*
|
|
||||||
* simple-prompt.js: Simple example of using prompt.
|
|
||||||
*
|
|
||||||
* (C) 2010, Nodejitsu Inc.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
var prompt = require('../lib/prompt');
|
|
||||||
|
|
||||||
//
|
|
||||||
// Start the prompt
|
|
||||||
//
|
|
||||||
prompt.start();
|
|
||||||
|
|
||||||
//
|
|
||||||
// Get two properties from the user: username and email
|
|
||||||
//
|
|
||||||
prompt.get(['username', 'email'], function (err, result) {
|
|
||||||
//
|
|
||||||
// Log the results.
|
|
||||||
//
|
|
||||||
console.log('Command-line input received:');
|
|
||||||
console.log(' username: ' + result.username);
|
|
||||||
console.log(' email: ' + result.email);
|
|
||||||
});
|
|
@ -1,32 +0,0 @@
|
|||||||
/*
|
|
||||||
* yes-or-no-prompt.js: Simple example of using prompt.
|
|
||||||
*
|
|
||||||
* (C) 2012, Nodejitsu Inc.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
var prompt = require('../lib/prompt');
|
|
||||||
|
|
||||||
//
|
|
||||||
// Start the prompt
|
|
||||||
//
|
|
||||||
prompt.start();
|
|
||||||
|
|
||||||
var property = {
|
|
||||||
name: 'yesno',
|
|
||||||
message: 'are you sure?',
|
|
||||||
validator: /y[es]*|n[o]?/,
|
|
||||||
warning: 'Must respond yes or no',
|
|
||||||
default: 'no'
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// Get the simple yes or no property
|
|
||||||
//
|
|
||||||
prompt.get(property, function (err, result) {
|
|
||||||
//
|
|
||||||
// Log the results.
|
|
||||||
//
|
|
||||||
console.log('Command-line input received:');
|
|
||||||
console.log(' result: ' + result.yesno);
|
|
||||||
});
|
|
@ -1,756 +0,0 @@
|
|||||||
/*
|
|
||||||
* prompt.js: Simple prompt for prompting information from the command line
|
|
||||||
*
|
|
||||||
* (C) 2010, Nodejitsu Inc.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
var events = require('events'),
|
|
||||||
readline = require('readline'),
|
|
||||||
utile = require('utile'),
|
|
||||||
async = utile.async,
|
|
||||||
read = require('read'),
|
|
||||||
validate = require('revalidator').validate,
|
|
||||||
winston = require('winston');
|
|
||||||
|
|
||||||
//
|
|
||||||
// Monkey-punch readline.Interface to work-around
|
|
||||||
// https://github.com/joyent/node/issues/3860
|
|
||||||
//
|
|
||||||
readline.Interface.prototype.setPrompt = function(prompt, length) {
|
|
||||||
this._prompt = prompt;
|
|
||||||
if (length) {
|
|
||||||
this._promptLength = length;
|
|
||||||
} else {
|
|
||||||
var lines = prompt.split(/[\r\n]/);
|
|
||||||
var lastLine = lines[lines.length - 1];
|
|
||||||
this._promptLength = lastLine.replace(/\u001b\[(\d+(;\d+)*)?m/g, '').length;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// Expose version using `pkginfo`
|
|
||||||
//
|
|
||||||
require('pkginfo')(module, 'version');
|
|
||||||
|
|
||||||
var stdin, stdout, history = [];
|
|
||||||
var prompt = module.exports = Object.create(events.EventEmitter.prototype);
|
|
||||||
var logger = prompt.logger = new winston.Logger({
|
|
||||||
transports: [new (winston.transports.Console)()]
|
|
||||||
});
|
|
||||||
|
|
||||||
prompt.started = false;
|
|
||||||
prompt.paused = false;
|
|
||||||
prompt.allowEmpty = false;
|
|
||||||
prompt.message = 'prompt';
|
|
||||||
prompt.delimiter = ': ';
|
|
||||||
prompt.colors = true;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Create an empty object for the properties
|
|
||||||
// known to `prompt`
|
|
||||||
//
|
|
||||||
prompt.properties = {};
|
|
||||||
|
|
||||||
//
|
|
||||||
// Setup the default winston logger to use
|
|
||||||
// the `cli` levels and colors.
|
|
||||||
//
|
|
||||||
logger.cli();
|
|
||||||
|
|
||||||
//
|
|
||||||
// ### function start (options)
|
|
||||||
// #### @options {Object} **Optional** Options to consume by prompt
|
|
||||||
// Starts the prompt by listening to the appropriate events on `options.stdin`
|
|
||||||
// and `options.stdout`. If no streams are supplied, then `process.stdin`
|
|
||||||
// and `process.stdout` are used, respectively.
|
|
||||||
//
|
|
||||||
prompt.start = function (options) {
|
|
||||||
if (prompt.started) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
options = options || {};
|
|
||||||
stdin = options.stdin || process.stdin;
|
|
||||||
stdout = options.stdout || process.stdout;
|
|
||||||
|
|
||||||
//
|
|
||||||
// By default: Remember the last `10` prompt property /
|
|
||||||
// answer pairs and don't allow empty responses globally.
|
|
||||||
//
|
|
||||||
prompt.memory = options.memory || 10;
|
|
||||||
prompt.allowEmpty = options.allowEmpty || false;
|
|
||||||
prompt.message = options.message || prompt.message;
|
|
||||||
prompt.delimiter = options.delimiter || prompt.delimiter;
|
|
||||||
prompt.colors = options.colors || prompt.colors;
|
|
||||||
|
|
||||||
if (process.platform !== 'win32') {
|
|
||||||
// windows falls apart trying to deal with SIGINT
|
|
||||||
process.on('SIGINT', function () {
|
|
||||||
stdout.write('\n');
|
|
||||||
process.exit(1);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
prompt.emit('start');
|
|
||||||
prompt.started = true;
|
|
||||||
return prompt;
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// ### function pause ()
|
|
||||||
// Pauses input coming in from stdin
|
|
||||||
//
|
|
||||||
prompt.pause = function () {
|
|
||||||
if (!prompt.started || prompt.paused) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
stdin.pause();
|
|
||||||
prompt.emit('pause');
|
|
||||||
prompt.paused = true;
|
|
||||||
return prompt;
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// ### function resume ()
|
|
||||||
// Resumes input coming in from stdin
|
|
||||||
//
|
|
||||||
prompt.resume = function () {
|
|
||||||
if (!prompt.started || !prompt.paused) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
stdin.resume();
|
|
||||||
prompt.emit('resume');
|
|
||||||
prompt.paused = false;
|
|
||||||
return prompt;
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// ### function history (search)
|
|
||||||
// #### @search {Number|string} Index or property name to find.
|
|
||||||
// Returns the `property:value` pair from within the prompts
|
|
||||||
// `history` array.
|
|
||||||
//
|
|
||||||
prompt.history = function (search) {
|
|
||||||
if (typeof search === 'number') {
|
|
||||||
return history[search] || {};
|
|
||||||
}
|
|
||||||
|
|
||||||
var names = history.map(function (pair) {
|
|
||||||
return typeof pair.property === 'string'
|
|
||||||
? pair.property
|
|
||||||
: pair.property.name;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!~names.indexOf(search)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return history.filter(function (pair) {
|
|
||||||
return typeof pair.property === 'string'
|
|
||||||
? pair.property === search
|
|
||||||
: pair.property.name === search;
|
|
||||||
})[0];
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// ### function get (schema, callback)
|
|
||||||
// #### @schema {Array|Object|string} Set of variables to get input for.
|
|
||||||
// #### @callback {function} Continuation to pass control to when complete.
|
|
||||||
// Gets input from the user via stdin for the specified message(s) `msg`.
|
|
||||||
//
|
|
||||||
prompt.get = function (schema, callback) {
|
|
||||||
//
|
|
||||||
// Transforms a full JSON-schema into an array describing path and sub-schemas.
|
|
||||||
// Used for iteration purposes.
|
|
||||||
//
|
|
||||||
function untangle(schema, path) {
|
|
||||||
var results = [];
|
|
||||||
path = path || [];
|
|
||||||
|
|
||||||
if (schema.properties) {
|
|
||||||
//
|
|
||||||
// Iterate over the properties in the schema and use recursion
|
|
||||||
// to process sub-properties.
|
|
||||||
//
|
|
||||||
Object.keys(schema.properties).forEach(function (key) {
|
|
||||||
var obj = {};
|
|
||||||
obj[key] = schema.properties[key];
|
|
||||||
|
|
||||||
//
|
|
||||||
// Concat a sub-untangling to the results.
|
|
||||||
//
|
|
||||||
results = results.concat(untangle(obj[key], path.concat(key)));
|
|
||||||
});
|
|
||||||
|
|
||||||
// Return the results.
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// This is a schema "leaf".
|
|
||||||
//
|
|
||||||
return {
|
|
||||||
path: path,
|
|
||||||
schema: schema
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Iterate over the values in the schema, represented as
|
|
||||||
// a legit single-property object subschemas. Accepts `schema`
|
|
||||||
// of the forms:
|
|
||||||
//
|
|
||||||
// 'prop-name'
|
|
||||||
//
|
|
||||||
// ['string-name', { path: ['or-well-formed-subschema'], properties: ... }]
|
|
||||||
//
|
|
||||||
// { path: ['or-well-formed-subschema'], properties: ... ] }
|
|
||||||
//
|
|
||||||
// { properties: { 'schema-with-no-path' } }
|
|
||||||
//
|
|
||||||
// And transforms them all into
|
|
||||||
//
|
|
||||||
// { path: ['path', 'to', 'property'], properties: { path: { to: ...} } }
|
|
||||||
//
|
|
||||||
function iterate(schema, get, done) {
|
|
||||||
var iterator = [],
|
|
||||||
result = {};
|
|
||||||
|
|
||||||
if (typeof schema === 'string') {
|
|
||||||
//
|
|
||||||
// We can iterate over a single string.
|
|
||||||
//
|
|
||||||
iterator.push({
|
|
||||||
path: [schema],
|
|
||||||
schema: prompt.properties[schema.toLowerCase()] || {}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else if (Array.isArray(schema)) {
|
|
||||||
//
|
|
||||||
// An array of strings and/or single-prop schema and/or no-prop schema.
|
|
||||||
//
|
|
||||||
iterator = schema.map(function (element) {
|
|
||||||
if (typeof element === 'string') {
|
|
||||||
return {
|
|
||||||
path: [element],
|
|
||||||
schema: prompt.properties[element.toLowerCase()] || {}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else if (element.properties) {
|
|
||||||
return {
|
|
||||||
path: [Object.keys(element.properties)[0]],
|
|
||||||
schema: element.properties[Object.keys(element.properties)[0]]
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else if (element.path && element.schema) {
|
|
||||||
return element;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return {
|
|
||||||
path: [element.name || 'question'],
|
|
||||||
schema: element
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else if (schema.properties) {
|
|
||||||
//
|
|
||||||
// Or a complete schema `untangle` it for use.
|
|
||||||
//
|
|
||||||
iterator = untangle(schema);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
//
|
|
||||||
// Or a partial schema and path.
|
|
||||||
// TODO: Evaluate need for this option.
|
|
||||||
//
|
|
||||||
iterator = [{
|
|
||||||
schema: schema.schema ? schema.schema : schema,
|
|
||||||
path: schema.path || [schema.name || 'question']
|
|
||||||
}];
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Now, iterate and assemble the result.
|
|
||||||
//
|
|
||||||
async.forEachSeries(iterator, function (branch, next) {
|
|
||||||
get(branch, function assembler(err, line) {
|
|
||||||
if (err) {
|
|
||||||
return next(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
function build(path, line) {
|
|
||||||
var obj = {};
|
|
||||||
if (path.length) {
|
|
||||||
obj[path[0]] = build(path.slice(1), line);
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
return line;
|
|
||||||
}
|
|
||||||
|
|
||||||
function attach(obj, attr) {
|
|
||||||
var keys;
|
|
||||||
if (typeof attr !== 'object' || attr instanceof Array) {
|
|
||||||
return attr;
|
|
||||||
}
|
|
||||||
|
|
||||||
keys = Object.keys(attr);
|
|
||||||
if (keys.length) {
|
|
||||||
if (!obj[keys[0]]) {
|
|
||||||
obj[keys[0]] = {};
|
|
||||||
}
|
|
||||||
obj[keys[0]] = attach(obj[keys[0]], attr[keys[0]]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = attach(result, build(branch.path, line));
|
|
||||||
next();
|
|
||||||
});
|
|
||||||
}, function (err) {
|
|
||||||
return err ? done(err) : done(null, result);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
iterate(schema, function get(target, next) {
|
|
||||||
prompt.getInput(target, function (err, line) {
|
|
||||||
return err ? next(err) : next(null, line);
|
|
||||||
});
|
|
||||||
}, callback);
|
|
||||||
|
|
||||||
return prompt;
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// ### function confirm (msg, callback)
|
|
||||||
// #### @msg {Array|Object|string} set of message to confirm
|
|
||||||
// #### @callback {function} Continuation to pass control to when complete.
|
|
||||||
// Confirms a single or series of messages by prompting the user for a Y/N response.
|
|
||||||
// Returns `true` if ALL messages are answered in the affirmative, otherwise `false`
|
|
||||||
//
|
|
||||||
// `msg` can be a string, or object (or array of strings/objects).
|
|
||||||
// An object may have the following properties:
|
|
||||||
//
|
|
||||||
// {
|
|
||||||
// description: 'yes/no' // message to prompt user
|
|
||||||
// pattern: /^[yntf]{1}/i // optional - regex defining acceptable responses
|
|
||||||
// yes: /^[yt]{1}/i // optional - regex defining `affirmative` responses
|
|
||||||
// message: 'yes/no' // optional - message to display for invalid responses
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
prompt.confirm = function (/* msg, options, callback */) {
|
|
||||||
var args = Array.prototype.slice.call(arguments),
|
|
||||||
msg = args.shift(),
|
|
||||||
callback = args.pop(),
|
|
||||||
opts = args.shift(),
|
|
||||||
vars = !Array.isArray(msg) ? [msg] : msg,
|
|
||||||
RX_Y = /^[yt]{1}/i,
|
|
||||||
RX_YN = /^[yntf]{1}/i;
|
|
||||||
|
|
||||||
function confirm(target, next) {
|
|
||||||
var yes = target.yes || RX_Y,
|
|
||||||
options = utile.mixin({
|
|
||||||
description: typeof target === 'string' ? target : target.description||'yes/no',
|
|
||||||
pattern: target.pattern || RX_YN,
|
|
||||||
name: 'confirm',
|
|
||||||
message: target.message || 'yes/no'
|
|
||||||
}, opts || {});
|
|
||||||
|
|
||||||
|
|
||||||
prompt.get([options], function (err, result) {
|
|
||||||
next(err ? false : yes.test(result[options.name]));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async.rejectSeries(vars, confirm, function(result) {
|
|
||||||
callback(null, result.length===0);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Variables needed outside of getInput for multiline arrays.
|
|
||||||
var tmp = [];
|
|
||||||
|
|
||||||
|
|
||||||
// ### function getInput (prop, callback)
|
|
||||||
// #### @prop {Object|string} Variable to get input for.
|
|
||||||
// #### @callback {function} Continuation to pass control to when complete.
|
|
||||||
// Gets input from the user via stdin for the specified message `msg`.
|
|
||||||
//
|
|
||||||
prompt.getInput = function (prop, callback) {
|
|
||||||
var schema = prop.schema || prop,
|
|
||||||
propName = prop.path && prop.path.join(':') || prop,
|
|
||||||
storedSchema = prompt.properties[propName.toLowerCase()],
|
|
||||||
delim = prompt.delimiter,
|
|
||||||
defaultLine,
|
|
||||||
against,
|
|
||||||
hidden,
|
|
||||||
length,
|
|
||||||
valid,
|
|
||||||
name,
|
|
||||||
raw,
|
|
||||||
msg;
|
|
||||||
|
|
||||||
//
|
|
||||||
// If there is a stored schema for `propName` in `propmpt.properties`
|
|
||||||
// then use it.
|
|
||||||
//
|
|
||||||
if (schema instanceof Object && !Object.keys(schema).length &&
|
|
||||||
typeof storedSchema !== 'undefined') {
|
|
||||||
schema = storedSchema;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Build a proper validation schema if we just have a string
|
|
||||||
// and no `storedSchema`.
|
|
||||||
//
|
|
||||||
if (typeof prop === 'string' && !storedSchema) {
|
|
||||||
schema = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
schema = convert(schema);
|
|
||||||
defaultLine = schema.default;
|
|
||||||
name = prop.description || schema.description || propName;
|
|
||||||
raw = prompt.colors
|
|
||||||
? [prompt.message, delim + name.grey, delim.grey]
|
|
||||||
: [prompt.message, delim + name, delim];
|
|
||||||
|
|
||||||
prop = {
|
|
||||||
schema: schema,
|
|
||||||
path: propName.split(':')
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// If the schema has no `properties` value then set
|
|
||||||
// it to an object containing the current schema
|
|
||||||
// for `propName`.
|
|
||||||
//
|
|
||||||
if (!schema.properties) {
|
|
||||||
schema = (function () {
|
|
||||||
var obj = { properties: {} };
|
|
||||||
obj.properties[propName] = schema;
|
|
||||||
return obj;
|
|
||||||
})();
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Handle overrides here.
|
|
||||||
// TODO: Make overrides nestable
|
|
||||||
//
|
|
||||||
if (prompt.override && prompt.override[propName]) {
|
|
||||||
if (prompt._performValidation(name, prop, prompt.override, schema, -1, callback)) {
|
|
||||||
return callback(null, prompt.override[propName]);
|
|
||||||
}
|
|
||||||
|
|
||||||
delete prompt.override[propName];
|
|
||||||
}
|
|
||||||
|
|
||||||
var type = (schema.properties && schema.properties[propName] &&
|
|
||||||
schema.properties[propName].type || '').toLowerCase().trim(),
|
|
||||||
wait = type === 'array';
|
|
||||||
|
|
||||||
if (type === 'array') {
|
|
||||||
length = prop.schema.maxItems;
|
|
||||||
if (length) {
|
|
||||||
msg = (tmp.length + 1).toString() + '/' + length.toString();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
msg = (tmp.length + 1).toString();
|
|
||||||
}
|
|
||||||
msg += delim;
|
|
||||||
raw.push(prompt.colors ? msg.grey : msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Calculate the raw length and colorize the prompt
|
|
||||||
//
|
|
||||||
length = raw.join('').length;
|
|
||||||
raw[0] = raw[0];
|
|
||||||
msg = raw.join('');
|
|
||||||
|
|
||||||
if (schema.help) {
|
|
||||||
schema.help.forEach(function (line) {
|
|
||||||
logger.help(line);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Emit a "prompting" event
|
|
||||||
//
|
|
||||||
prompt.emit('prompt', prop);
|
|
||||||
|
|
||||||
//
|
|
||||||
// If there is no default line, set it to an empty string
|
|
||||||
//
|
|
||||||
if(typeof defaultLine === 'undefined') {
|
|
||||||
defaultLine = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// set to string for readline ( will not accept Numbers )
|
|
||||||
//
|
|
||||||
defaultLine = defaultLine.toString();
|
|
||||||
|
|
||||||
//
|
|
||||||
// Make the actual read
|
|
||||||
//
|
|
||||||
read({
|
|
||||||
prompt: msg,
|
|
||||||
silent: prop.schema && prop.schema.hidden,
|
|
||||||
default: defaultLine,
|
|
||||||
input: stdin,
|
|
||||||
output: stdout
|
|
||||||
}, function (err, line) {
|
|
||||||
if (err && wait === false) {
|
|
||||||
return callback(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
var against = {},
|
|
||||||
numericInput,
|
|
||||||
isValid;
|
|
||||||
|
|
||||||
if (line !== '') {
|
|
||||||
|
|
||||||
if (schema.properties[propName]) {
|
|
||||||
var type = (schema.properties[propName].type || '').toLowerCase().trim() || undefined;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Attempt to parse input as a float if the schema expects a number.
|
|
||||||
//
|
|
||||||
if (type == 'number') {
|
|
||||||
numericInput = parseFloat(line, 10);
|
|
||||||
if (!isNaN(numericInput)) {
|
|
||||||
line = numericInput;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Attempt to parse input as a boolean if the schema expects a boolean
|
|
||||||
//
|
|
||||||
if (type == 'boolean') {
|
|
||||||
if(line === "true") {
|
|
||||||
line = true;
|
|
||||||
}
|
|
||||||
if(line === "false") {
|
|
||||||
line = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// If the type is an array, wait for the end. Fixes #54
|
|
||||||
//
|
|
||||||
if (type == 'array') {
|
|
||||||
var length = prop.schema.maxItems;
|
|
||||||
if (err) {
|
|
||||||
if (err.message == 'canceled') {
|
|
||||||
wait = false;
|
|
||||||
stdout.write('\n');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (length) {
|
|
||||||
if (tmp.length + 1 < length) {
|
|
||||||
isValid = false;
|
|
||||||
wait = true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
isValid = true;
|
|
||||||
wait = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
isValid = false;
|
|
||||||
wait = true;
|
|
||||||
}
|
|
||||||
tmp.push(line);
|
|
||||||
}
|
|
||||||
line = tmp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
against[propName] = line;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (prop && prop.schema.before) {
|
|
||||||
line = prop.schema.before(line);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate
|
|
||||||
if (isValid === undefined) isValid = prompt._performValidation(name, prop, against, schema, line, callback);
|
|
||||||
|
|
||||||
if (!isValid) {
|
|
||||||
return prompt.getInput(prop, callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Log the resulting line, append this `property:value`
|
|
||||||
// pair to the history for `prompt` and respond to
|
|
||||||
// the callback.
|
|
||||||
//
|
|
||||||
logger.input(line.yellow);
|
|
||||||
prompt._remember(propName, line);
|
|
||||||
callback(null, line);
|
|
||||||
|
|
||||||
// Make sure `tmp` is emptied
|
|
||||||
tmp = [];
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// ### function performValidation (name, prop, against, schema, line, callback)
|
|
||||||
// #### @name {Object} Variable name
|
|
||||||
// #### @prop {Object|string} Variable to get input for.
|
|
||||||
// #### @against {Object} Input
|
|
||||||
// #### @schema {Object} Validation schema
|
|
||||||
// #### @line {String|Boolean} Input line
|
|
||||||
// #### @callback {function} Continuation to pass control to when complete.
|
|
||||||
// Perfoms user input validation, print errors if needed and returns value according to validation
|
|
||||||
//
|
|
||||||
prompt._performValidation = function (name, prop, against, schema, line, callback) {
|
|
||||||
var numericInput, valid, msg;
|
|
||||||
|
|
||||||
try {
|
|
||||||
valid = validate(against, schema);
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
return (line !== -1) ? callback(err) : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!valid.valid) {
|
|
||||||
msg = line !== -1 ? 'Invalid input for ' : 'Invalid command-line input for ';
|
|
||||||
|
|
||||||
if (prompt.colors) {
|
|
||||||
logger.error(msg + name.grey);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
logger.error(msg + name);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (prop.schema.message) {
|
|
||||||
logger.error(prop.schema.message);
|
|
||||||
}
|
|
||||||
|
|
||||||
prompt.emit('invalid', prop, line);
|
|
||||||
}
|
|
||||||
|
|
||||||
return valid.valid;
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// ### function addProperties (obj, properties, callback)
|
|
||||||
// #### @obj {Object} Object to add properties to
|
|
||||||
// #### @properties {Array} List of properties to get values for
|
|
||||||
// #### @callback {function} Continuation to pass control to when complete.
|
|
||||||
// Prompts the user for values each of the `properties` if `obj` does not already
|
|
||||||
// have a value for the property. Responds with the modified object.
|
|
||||||
//
|
|
||||||
prompt.addProperties = function (obj, properties, callback) {
|
|
||||||
properties = properties.filter(function (prop) {
|
|
||||||
return typeof obj[prop] === 'undefined';
|
|
||||||
});
|
|
||||||
|
|
||||||
if (properties.length === 0) {
|
|
||||||
return callback(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
prompt.get(properties, function (err, results) {
|
|
||||||
if (err) {
|
|
||||||
return callback(err);
|
|
||||||
}
|
|
||||||
else if (!results) {
|
|
||||||
return callback(null, obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
function putNested (obj, path, value) {
|
|
||||||
var last = obj, key;
|
|
||||||
|
|
||||||
while (path.length > 1) {
|
|
||||||
key = path.shift();
|
|
||||||
if (!last[key]) {
|
|
||||||
last[key] = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
last = last[key];
|
|
||||||
}
|
|
||||||
|
|
||||||
last[path.shift()] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
Object.keys(results).forEach(function (key) {
|
|
||||||
putNested(obj, key.split('.'), results[key]);
|
|
||||||
});
|
|
||||||
|
|
||||||
callback(null, obj);
|
|
||||||
});
|
|
||||||
|
|
||||||
return prompt;
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// ### @private function _remember (property, value)
|
|
||||||
// #### @property {Object|string} Property that the value is in response to.
|
|
||||||
// #### @value {string} User input captured by `prompt`.
|
|
||||||
// Prepends the `property:value` pair into the private `history` Array
|
|
||||||
// for `prompt` so that it can be accessed later.
|
|
||||||
//
|
|
||||||
prompt._remember = function (property, value) {
|
|
||||||
history.unshift({
|
|
||||||
property: property,
|
|
||||||
value: value
|
|
||||||
});
|
|
||||||
|
|
||||||
//
|
|
||||||
// If the length of the `history` Array
|
|
||||||
// has exceeded the specified length to remember,
|
|
||||||
// `prompt.memory`, truncate it.
|
|
||||||
//
|
|
||||||
if (history.length > prompt.memory) {
|
|
||||||
history.splice(prompt.memory, history.length - prompt.memory);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// ### @private function convert (schema)
|
|
||||||
// #### @schema {Object} Schema for a property
|
|
||||||
// Converts the schema into new format if it is in old format
|
|
||||||
//
|
|
||||||
function convert(schema) {
|
|
||||||
var newProps = Object.keys(validate.messages),
|
|
||||||
newSchema = false,
|
|
||||||
key;
|
|
||||||
|
|
||||||
newProps = newProps.concat(['description', 'dependencies']);
|
|
||||||
|
|
||||||
for (key in schema) {
|
|
||||||
if (newProps.indexOf(key) > 0) {
|
|
||||||
newSchema = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!newSchema || schema.validator || schema.warning || typeof schema.empty !== 'undefined') {
|
|
||||||
schema.description = schema.message;
|
|
||||||
schema.message = schema.warning;
|
|
||||||
|
|
||||||
if (typeof schema.validator === 'function') {
|
|
||||||
schema.conform = schema.validator;
|
|
||||||
} else {
|
|
||||||
schema.pattern = schema.validator;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof schema.empty !== 'undefined') {
|
|
||||||
schema.required = !(schema.empty);
|
|
||||||
}
|
|
||||||
|
|
||||||
delete schema.warning;
|
|
||||||
delete schema.validator;
|
|
||||||
delete schema.empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
return schema;
|
|
||||||
}
|
|
@ -1,2 +0,0 @@
|
|||||||
node_modules/
|
|
||||||
npm-debug.log
|
|
@ -1,19 +0,0 @@
|
|||||||
Copyright (c) 2010 Charlie Robbins.
|
|
||||||
|
|
||||||
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.
|
|
@ -1,86 +0,0 @@
|
|||||||
# node-pkginfo
|
|
||||||
|
|
||||||
An easy way to expose properties on a module from a package.json
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
### Installing npm (node package manager)
|
|
||||||
```
|
|
||||||
curl http://npmjs.org/install.sh | sh
|
|
||||||
```
|
|
||||||
|
|
||||||
### Installing pkginfo
|
|
||||||
```
|
|
||||||
[sudo] npm install pkginfo
|
|
||||||
```
|
|
||||||
|
|
||||||
## Motivation
|
|
||||||
How often when writing node.js modules have you written the following line(s) of code?
|
|
||||||
|
|
||||||
* Hard code your version string into your code
|
|
||||||
|
|
||||||
``` js
|
|
||||||
exports.version = '0.1.0';
|
|
||||||
```
|
|
||||||
|
|
||||||
* Programmatically expose the version from the package.json
|
|
||||||
|
|
||||||
``` js
|
|
||||||
exports.version = JSON.parse(fs.readFileSync('/path/to/package.json', 'utf8')).version;
|
|
||||||
```
|
|
||||||
|
|
||||||
In other words, how often have you wanted to expose basic information from your package.json onto your module programmatically? **WELL NOW YOU CAN!**
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
Using `pkginfo` is idiot-proof, just require and invoke it.
|
|
||||||
|
|
||||||
``` js
|
|
||||||
var pkginfo = require('pkginfo')(module);
|
|
||||||
|
|
||||||
console.dir(module.exports);
|
|
||||||
```
|
|
||||||
|
|
||||||
By invoking the `pkginfo` module all of the properties in your `package.json` file will be automatically exposed on the callee module (i.e. the parent module of `pkginfo`).
|
|
||||||
|
|
||||||
Here's a sample of the output:
|
|
||||||
|
|
||||||
```
|
|
||||||
{ name: 'simple-app',
|
|
||||||
description: 'A test fixture for pkginfo',
|
|
||||||
version: '0.1.0',
|
|
||||||
author: 'Charlie Robbins <charlie.robbins@gmail.com>',
|
|
||||||
keywords: [ 'test', 'fixture' ],
|
|
||||||
main: './index.js',
|
|
||||||
scripts: { test: 'vows test/*-test.js --spec' },
|
|
||||||
engines: { node: '>= 0.4.0' } }
|
|
||||||
```
|
|
||||||
|
|
||||||
### Expose specific properties
|
|
||||||
If you don't want to expose **all** properties on from your `package.json` on your module then simple pass those properties to the `pkginfo` function:
|
|
||||||
|
|
||||||
``` js
|
|
||||||
var pkginfo = require('pkginfo')(module, 'version', 'author');
|
|
||||||
|
|
||||||
console.dir(module.exports);
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
{ version: '0.1.0',
|
|
||||||
author: 'Charlie Robbins <charlie.robbins@gmail.com>' }
|
|
||||||
```
|
|
||||||
|
|
||||||
If you're looking for further usage see the [examples][0] included in this repository.
|
|
||||||
|
|
||||||
## Run Tests
|
|
||||||
Tests are written in [vows][1] and give complete coverage of all APIs.
|
|
||||||
|
|
||||||
```
|
|
||||||
vows test/*-test.js --spec
|
|
||||||
```
|
|
||||||
|
|
||||||
[0]: https://github.com/indexzero/node-pkginfo/tree/master/examples
|
|
||||||
[1]: http://vowsjs.org
|
|
||||||
|
|
||||||
#### Author: [Charlie Robbins](http://nodejitsu.com)
|
|
||||||
#### License: MIT
|
|
@ -1,194 +0,0 @@
|
|||||||
/*--------------------- Layout and Typography ----------------------------*/
|
|
||||||
body {
|
|
||||||
font-family: 'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif;
|
|
||||||
font-size: 15px;
|
|
||||||
line-height: 22px;
|
|
||||||
color: #252519;
|
|
||||||
margin: 0; padding: 0;
|
|
||||||
}
|
|
||||||
a {
|
|
||||||
color: #261a3b;
|
|
||||||
}
|
|
||||||
a:visited {
|
|
||||||
color: #261a3b;
|
|
||||||
}
|
|
||||||
p {
|
|
||||||
margin: 0 0 15px 0;
|
|
||||||
}
|
|
||||||
h4, h5, h6 {
|
|
||||||
color: #333;
|
|
||||||
margin: 6px 0 6px 0;
|
|
||||||
font-size: 13px;
|
|
||||||
}
|
|
||||||
h2, h3 {
|
|
||||||
margin-bottom: 0;
|
|
||||||
color: #000;
|
|
||||||
}
|
|
||||||
h1 {
|
|
||||||
margin-top: 40px;
|
|
||||||
margin-bottom: 15px;
|
|
||||||
color: #000;
|
|
||||||
}
|
|
||||||
#container {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
#background {
|
|
||||||
position: fixed;
|
|
||||||
top: 0; left: 525px; right: 0; bottom: 0;
|
|
||||||
background: #f5f5ff;
|
|
||||||
border-left: 1px solid #e5e5ee;
|
|
||||||
z-index: -1;
|
|
||||||
}
|
|
||||||
#jump_to, #jump_page {
|
|
||||||
background: white;
|
|
||||||
-webkit-box-shadow: 0 0 25px #777; -moz-box-shadow: 0 0 25px #777;
|
|
||||||
-webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomleft: 5px;
|
|
||||||
font: 10px Arial;
|
|
||||||
text-transform: uppercase;
|
|
||||||
cursor: pointer;
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
#jump_to, #jump_wrapper {
|
|
||||||
position: fixed;
|
|
||||||
right: 0; top: 0;
|
|
||||||
padding: 5px 10px;
|
|
||||||
}
|
|
||||||
#jump_wrapper {
|
|
||||||
padding: 0;
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
#jump_to:hover #jump_wrapper {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
#jump_page {
|
|
||||||
padding: 5px 0 3px;
|
|
||||||
margin: 0 0 25px 25px;
|
|
||||||
}
|
|
||||||
#jump_page .source {
|
|
||||||
display: block;
|
|
||||||
padding: 5px 10px;
|
|
||||||
text-decoration: none;
|
|
||||||
border-top: 1px solid #eee;
|
|
||||||
}
|
|
||||||
#jump_page .source:hover {
|
|
||||||
background: #f5f5ff;
|
|
||||||
}
|
|
||||||
#jump_page .source:first-child {
|
|
||||||
}
|
|
||||||
table td {
|
|
||||||
border: 0;
|
|
||||||
outline: 0;
|
|
||||||
}
|
|
||||||
td.docs, th.docs {
|
|
||||||
max-width: 450px;
|
|
||||||
min-width: 450px;
|
|
||||||
min-height: 5px;
|
|
||||||
padding: 10px 25px 1px 50px;
|
|
||||||
overflow-x: hidden;
|
|
||||||
vertical-align: top;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
.docs pre {
|
|
||||||
margin: 15px 0 15px;
|
|
||||||
padding-left: 15px;
|
|
||||||
}
|
|
||||||
.docs p tt, .docs p code {
|
|
||||||
background: #f8f8ff;
|
|
||||||
border: 1px solid #dedede;
|
|
||||||
font-size: 12px;
|
|
||||||
padding: 0 0.2em;
|
|
||||||
}
|
|
||||||
.pilwrap {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
.pilcrow {
|
|
||||||
font: 12px Arial;
|
|
||||||
text-decoration: none;
|
|
||||||
color: #454545;
|
|
||||||
position: absolute;
|
|
||||||
top: 3px; left: -20px;
|
|
||||||
padding: 1px 2px;
|
|
||||||
opacity: 0;
|
|
||||||
-webkit-transition: opacity 0.2s linear;
|
|
||||||
}
|
|
||||||
td.docs:hover .pilcrow {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
td.code, th.code {
|
|
||||||
padding: 14px 15px 16px 25px;
|
|
||||||
width: 100%;
|
|
||||||
vertical-align: top;
|
|
||||||
background: #f5f5ff;
|
|
||||||
border-left: 1px solid #e5e5ee;
|
|
||||||
}
|
|
||||||
pre, tt, code {
|
|
||||||
font-size: 12px; line-height: 18px;
|
|
||||||
font-family: Menlo, Monaco, Consolas, "Lucida Console", monospace;
|
|
||||||
margin: 0; padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*---------------------- Syntax Highlighting -----------------------------*/
|
|
||||||
td.linenos { background-color: #f0f0f0; padding-right: 10px; }
|
|
||||||
span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; }
|
|
||||||
body .hll { background-color: #ffffcc }
|
|
||||||
body .c { color: #408080; font-style: italic } /* Comment */
|
|
||||||
body .err { border: 1px solid #FF0000 } /* Error */
|
|
||||||
body .k { color: #954121 } /* Keyword */
|
|
||||||
body .o { color: #666666 } /* Operator */
|
|
||||||
body .cm { color: #408080; font-style: italic } /* Comment.Multiline */
|
|
||||||
body .cp { color: #BC7A00 } /* Comment.Preproc */
|
|
||||||
body .c1 { color: #408080; font-style: italic } /* Comment.Single */
|
|
||||||
body .cs { color: #408080; font-style: italic } /* Comment.Special */
|
|
||||||
body .gd { color: #A00000 } /* Generic.Deleted */
|
|
||||||
body .ge { font-style: italic } /* Generic.Emph */
|
|
||||||
body .gr { color: #FF0000 } /* Generic.Error */
|
|
||||||
body .gh { color: #000080; font-weight: bold } /* Generic.Heading */
|
|
||||||
body .gi { color: #00A000 } /* Generic.Inserted */
|
|
||||||
body .go { color: #808080 } /* Generic.Output */
|
|
||||||
body .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
|
|
||||||
body .gs { font-weight: bold } /* Generic.Strong */
|
|
||||||
body .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
|
|
||||||
body .gt { color: #0040D0 } /* Generic.Traceback */
|
|
||||||
body .kc { color: #954121 } /* Keyword.Constant */
|
|
||||||
body .kd { color: #954121; font-weight: bold } /* Keyword.Declaration */
|
|
||||||
body .kn { color: #954121; font-weight: bold } /* Keyword.Namespace */
|
|
||||||
body .kp { color: #954121 } /* Keyword.Pseudo */
|
|
||||||
body .kr { color: #954121; font-weight: bold } /* Keyword.Reserved */
|
|
||||||
body .kt { color: #B00040 } /* Keyword.Type */
|
|
||||||
body .m { color: #666666 } /* Literal.Number */
|
|
||||||
body .s { color: #219161 } /* Literal.String */
|
|
||||||
body .na { color: #7D9029 } /* Name.Attribute */
|
|
||||||
body .nb { color: #954121 } /* Name.Builtin */
|
|
||||||
body .nc { color: #0000FF; font-weight: bold } /* Name.Class */
|
|
||||||
body .no { color: #880000 } /* Name.Constant */
|
|
||||||
body .nd { color: #AA22FF } /* Name.Decorator */
|
|
||||||
body .ni { color: #999999; font-weight: bold } /* Name.Entity */
|
|
||||||
body .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
|
|
||||||
body .nf { color: #0000FF } /* Name.Function */
|
|
||||||
body .nl { color: #A0A000 } /* Name.Label */
|
|
||||||
body .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
|
|
||||||
body .nt { color: #954121; font-weight: bold } /* Name.Tag */
|
|
||||||
body .nv { color: #19469D } /* Name.Variable */
|
|
||||||
body .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
|
|
||||||
body .w { color: #bbbbbb } /* Text.Whitespace */
|
|
||||||
body .mf { color: #666666 } /* Literal.Number.Float */
|
|
||||||
body .mh { color: #666666 } /* Literal.Number.Hex */
|
|
||||||
body .mi { color: #666666 } /* Literal.Number.Integer */
|
|
||||||
body .mo { color: #666666 } /* Literal.Number.Oct */
|
|
||||||
body .sb { color: #219161 } /* Literal.String.Backtick */
|
|
||||||
body .sc { color: #219161 } /* Literal.String.Char */
|
|
||||||
body .sd { color: #219161; font-style: italic } /* Literal.String.Doc */
|
|
||||||
body .s2 { color: #219161 } /* Literal.String.Double */
|
|
||||||
body .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
|
|
||||||
body .sh { color: #219161 } /* Literal.String.Heredoc */
|
|
||||||
body .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
|
|
||||||
body .sx { color: #954121 } /* Literal.String.Other */
|
|
||||||
body .sr { color: #BB6688 } /* Literal.String.Regex */
|
|
||||||
body .s1 { color: #219161 } /* Literal.String.Single */
|
|
||||||
body .ss { color: #19469D } /* Literal.String.Symbol */
|
|
||||||
body .bp { color: #954121 } /* Name.Builtin.Pseudo */
|
|
||||||
body .vc { color: #19469D } /* Name.Variable.Class */
|
|
||||||
body .vg { color: #19469D } /* Name.Variable.Global */
|
|
||||||
body .vi { color: #19469D } /* Name.Variable.Instance */
|
|
||||||
body .il { color: #666666 } /* Literal.Number.Integer.Long */
|
|
@ -1,101 +0,0 @@
|
|||||||
<!DOCTYPE html> <html> <head> <title>pkginfo.js</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> pkginfo.js </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-1">¶</a> </div> </td> <td class="code"> <div class="highlight"><pre><span class="cm">/*</span>
|
|
||||||
<span class="cm"> * pkginfo.js: Top-level include for the pkginfo module</span>
|
|
||||||
<span class="cm"> *</span>
|
|
||||||
<span class="cm"> * (C) 2011, Charlie Robbins</span>
|
|
||||||
<span class="cm"> *</span>
|
|
||||||
<span class="cm"> */</span>
|
|
||||||
|
|
||||||
<span class="kd">var</span> <span class="nx">fs</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'fs'</span><span class="p">),</span>
|
|
||||||
<span class="nx">path</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'path'</span><span class="p">);</span></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">¶</a> </div> <h3>function pkginfo ([options, 'property', 'property' ..])</h3>
|
|
||||||
|
|
||||||
<h4>@pmodule {Module} Parent module to read from.</h4>
|
|
||||||
|
|
||||||
<h4>@options {Object|Array|string} <strong>Optional</strong> Options used when exposing properties.</h4>
|
|
||||||
|
|
||||||
<h4>@arguments {string...} <strong>Optional</strong> Specified properties to expose.</h4>
|
|
||||||
|
|
||||||
<p>Exposes properties from the package.json file for the parent module on
|
|
||||||
it's exports. Valid usage:</p>
|
|
||||||
|
|
||||||
<p><code>require('pkginfo')()</code></p>
|
|
||||||
|
|
||||||
<p><code>require('pkginfo')('version', 'author');</code></p>
|
|
||||||
|
|
||||||
<p><code>require('pkginfo')(['version', 'author']);</code></p>
|
|
||||||
|
|
||||||
<p><code>require('pkginfo')({ include: ['version', 'author'] });</code></p> </td> <td class="code"> <div class="highlight"><pre><span class="kd">var</span> <span class="nx">pkginfo</span> <span class="o">=</span> <span class="nx">module</span><span class="p">.</span><span class="nx">exports</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">pmodule</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="p">{</span>
|
|
||||||
<span class="kd">var</span> <span class="nx">args</span> <span class="o">=</span> <span class="p">[].</span><span class="nx">slice</span><span class="p">.</span><span class="nx">call</span><span class="p">(</span><span class="nx">arguments</span><span class="p">,</span> <span class="mi">2</span><span class="p">).</span><span class="nx">filter</span><span class="p">(</span><span class="kd">function</span> <span class="p">(</span><span class="nx">arg</span><span class="p">)</span> <span class="p">{</span>
|
|
||||||
<span class="k">return</span> <span class="k">typeof</span> <span class="nx">arg</span> <span class="o">===</span> <span class="s1">'string'</span><span class="p">;</span>
|
|
||||||
<span class="p">});</span>
|
|
||||||
</pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">¶</a> </div> <p><strong>Parse variable arguments</strong></p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="p">(</span><span class="nb">Array</span><span class="p">.</span><span class="nx">isArray</span><span class="p">(</span><span class="nx">options</span><span class="p">))</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">¶</a> </div> <p>If the options passed in is an Array assume that
|
|
||||||
it is the Array of properties to expose from the
|
|
||||||
on the package.json file on the parent module.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">options</span> <span class="o">=</span> <span class="p">{</span> <span class="nx">include</span><span class="o">:</span> <span class="nx">options</span> <span class="p">};</span>
|
|
||||||
<span class="p">}</span>
|
|
||||||
<span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="k">typeof</span> <span class="nx">options</span> <span class="o">===</span> <span class="s1">'string'</span><span class="p">)</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">¶</a> </div> <p>Otherwise if the first argument is a string, then
|
|
||||||
assume that it is the first property to expose from
|
|
||||||
the package.json file on the parent module.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">options</span> <span class="o">=</span> <span class="p">{</span> <span class="nx">include</span><span class="o">:</span> <span class="p">[</span><span class="nx">options</span><span class="p">]</span> <span class="p">};</span>
|
|
||||||
<span class="p">}</span>
|
|
||||||
</pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">¶</a> </div> <p><strong>Setup default options</strong></p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">options</span> <span class="o">=</span> <span class="nx">options</span> <span class="o">||</span> <span class="p">{</span> <span class="nx">include</span><span class="o">:</span> <span class="p">[]</span> <span class="p">};</span>
|
|
||||||
|
|
||||||
<span class="k">if</span> <span class="p">(</span><span class="nx">args</span><span class="p">.</span><span class="nx">length</span> <span class="o">></span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">¶</a> </div> <p>If additional string arguments have been passed in
|
|
||||||
then add them to the properties to expose on the
|
|
||||||
parent module. </p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">options</span><span class="p">.</span><span class="nx">include</span> <span class="o">=</span> <span class="nx">options</span><span class="p">.</span><span class="nx">include</span><span class="p">.</span><span class="nx">concat</span><span class="p">(</span><span class="nx">args</span><span class="p">);</span>
|
|
||||||
<span class="p">}</span>
|
|
||||||
|
|
||||||
<span class="kd">var</span> <span class="nx">pkg</span> <span class="o">=</span> <span class="nx">pkginfo</span><span class="p">.</span><span class="nx">read</span><span class="p">(</span><span class="nx">pmodule</span><span class="p">,</span> <span class="nx">options</span><span class="p">.</span><span class="nx">dir</span><span class="p">).</span><span class="kr">package</span><span class="p">;</span>
|
|
||||||
<span class="nb">Object</span><span class="p">.</span><span class="nx">keys</span><span class="p">(</span><span class="nx">pkg</span><span class="p">).</span><span class="nx">forEach</span><span class="p">(</span><span class="kd">function</span> <span class="p">(</span><span class="nx">key</span><span class="p">)</span> <span class="p">{</span>
|
|
||||||
<span class="k">if</span> <span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">include</span><span class="p">.</span><span class="nx">length</span> <span class="o">></span> <span class="mi">0</span> <span class="o">&&</span> <span class="o">!~</span><span class="nx">options</span><span class="p">.</span><span class="nx">include</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="nx">key</span><span class="p">))</span> <span class="p">{</span>
|
|
||||||
<span class="k">return</span><span class="p">;</span>
|
|
||||||
<span class="p">}</span>
|
|
||||||
|
|
||||||
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">pmodule</span><span class="p">.</span><span class="nx">exports</span><span class="p">[</span><span class="nx">key</span><span class="p">])</span> <span class="p">{</span>
|
|
||||||
<span class="nx">pmodule</span><span class="p">.</span><span class="nx">exports</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span> <span class="o">=</span> <span class="nx">pkg</span><span class="p">[</span><span class="nx">key</span><span class="p">];</span>
|
|
||||||
<span class="p">}</span>
|
|
||||||
<span class="p">});</span>
|
|
||||||
|
|
||||||
<span class="k">return</span> <span class="nx">pkginfo</span><span class="p">;</span>
|
|
||||||
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">¶</a> </div> <h3>function find (dir)</h3>
|
|
||||||
|
|
||||||
<h4>@pmodule {Module} Parent module to read from.</h4>
|
|
||||||
|
|
||||||
<h4>@dir {string} <strong>Optional</strong> Directory to start search from.</h4>
|
|
||||||
|
|
||||||
<p>Searches up the directory tree from <code>dir</code> until it finds a directory
|
|
||||||
which contains a <code>package.json</code> file. </p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">pkginfo</span><span class="p">.</span><span class="nx">find</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">pmodule</span><span class="p">,</span> <span class="nx">dir</span><span class="p">)</span> <span class="p">{</span>
|
|
||||||
<span class="nx">dir</span> <span class="o">=</span> <span class="nx">dir</span> <span class="o">||</span> <span class="nx">pmodule</span><span class="p">.</span><span class="nx">filename</span><span class="p">;</span>
|
|
||||||
<span class="nx">dir</span> <span class="o">=</span> <span class="nx">path</span><span class="p">.</span><span class="nx">dirname</span><span class="p">(</span><span class="nx">dir</span><span class="p">);</span>
|
|
||||||
|
|
||||||
<span class="kd">var</span> <span class="nx">files</span> <span class="o">=</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">readdirSync</span><span class="p">(</span><span class="nx">dir</span><span class="p">);</span>
|
|
||||||
|
|
||||||
<span class="k">if</span> <span class="p">(</span><span class="o">~</span><span class="nx">files</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="s1">'package.json'</span><span class="p">))</span> <span class="p">{</span>
|
|
||||||
<span class="k">return</span> <span class="nx">path</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="nx">dir</span><span class="p">,</span> <span class="s1">'package.json'</span><span class="p">);</span>
|
|
||||||
<span class="p">}</span>
|
|
||||||
|
|
||||||
<span class="k">if</span> <span class="p">(</span><span class="nx">dir</span> <span class="o">===</span> <span class="s1">'/'</span><span class="p">)</span> <span class="p">{</span>
|
|
||||||
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span><span class="p">(</span><span class="s1">'Could not find package.json up from: '</span> <span class="o">+</span> <span class="nx">dir</span><span class="p">);</span>
|
|
||||||
<span class="p">}</span>
|
|
||||||
|
|
||||||
<span class="k">return</span> <span class="nx">pkginfo</span><span class="p">.</span><span class="nx">find</span><span class="p">(</span><span class="nx">dir</span><span class="p">);</span>
|
|
||||||
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">¶</a> </div> <h3>function read (pmodule, dir)</h3>
|
|
||||||
|
|
||||||
<h4>@pmodule {Module} Parent module to read from.</h4>
|
|
||||||
|
|
||||||
<h4>@dir {string} <strong>Optional</strong> Directory to start search from.</h4>
|
|
||||||
|
|
||||||
<p>Searches up the directory tree from <code>dir</code> until it finds a directory
|
|
||||||
which contains a <code>package.json</code> file and returns the package information.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">pkginfo</span><span class="p">.</span><span class="nx">read</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">pmodule</span><span class="p">,</span> <span class="nx">dir</span><span class="p">)</span> <span class="p">{</span>
|
|
||||||
<span class="nx">dir</span> <span class="o">=</span> <span class="nx">pkginfo</span><span class="p">.</span><span class="nx">find</span><span class="p">(</span><span class="nx">pmodule</span><span class="p">,</span> <span class="nx">dir</span><span class="p">);</span>
|
|
||||||
|
|
||||||
<span class="kd">var</span> <span class="nx">data</span> <span class="o">=</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">readFileSync</span><span class="p">(</span><span class="nx">dir</span><span class="p">).</span><span class="nx">toString</span><span class="p">();</span>
|
|
||||||
|
|
||||||
<span class="k">return</span> <span class="p">{</span>
|
|
||||||
<span class="nx">dir</span><span class="o">:</span> <span class="nx">dir</span><span class="p">,</span>
|
|
||||||
<span class="kr">package</span><span class="o">:</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span>
|
|
||||||
<span class="p">};</span>
|
|
||||||
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">¶</a> </div> <p>Call <code>pkginfo</code> on this module and expose version.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">pkginfo</span><span class="p">(</span><span class="nx">module</span><span class="p">,</span> <span class="p">{</span>
|
|
||||||
<span class="nx">dir</span><span class="o">:</span> <span class="nx">__dirname</span><span class="p">,</span>
|
|
||||||
<span class="nx">include</span><span class="o">:</span> <span class="p">[</span><span class="s1">'version'</span><span class="p">],</span>
|
|
||||||
<span class="nx">target</span><span class="o">:</span> <span class="nx">pkginfo</span>
|
|
||||||
<span class="p">});</span>
|
|
||||||
|
|
||||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
|
@ -1,19 +0,0 @@
|
|||||||
/*
|
|
||||||
* all-properties.js: Sample of including all properties from a package.json file
|
|
||||||
*
|
|
||||||
* (C) 2011, Charlie Robbins
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
var util = require('util'),
|
|
||||||
pkginfo = require('../lib/pkginfo')(module);
|
|
||||||
|
|
||||||
exports.someFunction = function () {
|
|
||||||
console.log('some of your custom logic here');
|
|
||||||
};
|
|
||||||
|
|
||||||
console.log('Inspecting module:');
|
|
||||||
console.dir(module.exports);
|
|
||||||
|
|
||||||
console.log('\nAll exports exposed:');
|
|
||||||
console.error(Object.keys(module.exports));
|
|
@ -1,20 +0,0 @@
|
|||||||
/*
|
|
||||||
* array-argument.js: Sample of including specific properties from a package.json file
|
|
||||||
* using Array argument syntax.
|
|
||||||
*
|
|
||||||
* (C) 2011, Charlie Robbins
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
var util = require('util'),
|
|
||||||
pkginfo = require('../lib/pkginfo')(module, ['version', 'author']);
|
|
||||||
|
|
||||||
exports.someFunction = function () {
|
|
||||||
console.log('some of your custom logic here');
|
|
||||||
};
|
|
||||||
|
|
||||||
console.log('Inspecting module:');
|
|
||||||
console.dir(module.exports);
|
|
||||||
|
|
||||||
console.log('\nAll exports exposed:');
|
|
||||||
console.error(Object.keys(module.exports));
|
|
@ -1,19 +0,0 @@
|
|||||||
/*
|
|
||||||
* multiple-properties.js: Sample of including multiple properties from a package.json file
|
|
||||||
*
|
|
||||||
* (C) 2011, Charlie Robbins
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
var util = require('util'),
|
|
||||||
pkginfo = require('../lib/pkginfo')(module, 'version', 'author');
|
|
||||||
|
|
||||||
exports.someFunction = function () {
|
|
||||||
console.log('some of your custom logic here');
|
|
||||||
};
|
|
||||||
|
|
||||||
console.log('Inspecting module:');
|
|
||||||
console.dir(module.exports);
|
|
||||||
|
|
||||||
console.log('\nAll exports exposed:');
|
|
||||||
console.error(Object.keys(module.exports));
|
|
@ -1,22 +0,0 @@
|
|||||||
/*
|
|
||||||
* object-argument.js: Sample of including specific properties from a package.json file
|
|
||||||
* using Object argument syntax.
|
|
||||||
*
|
|
||||||
* (C) 2011, Charlie Robbins
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
var util = require('util'),
|
|
||||||
pkginfo = require('../lib/pkginfo')(module, {
|
|
||||||
include: ['version', 'author']
|
|
||||||
});
|
|
||||||
|
|
||||||
exports.someFunction = function () {
|
|
||||||
console.log('some of your custom logic here');
|
|
||||||
};
|
|
||||||
|
|
||||||
console.log('Inspecting module:');
|
|
||||||
console.dir(module.exports);
|
|
||||||
|
|
||||||
console.log('\nAll exports exposed:');
|
|
||||||
console.error(Object.keys(module.exports));
|
|
@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "simple-app",
|
|
||||||
"description": "A test fixture for pkginfo",
|
|
||||||
"version": "0.1.0",
|
|
||||||
"author": "Charlie Robbins <charlie.robbins@gmail.com>",
|
|
||||||
"keywords": ["test", "fixture"],
|
|
||||||
"main": "./index.js",
|
|
||||||
"scripts": { "test": "vows test/*-test.js --spec" },
|
|
||||||
"engines": { "node": ">= 0.4.0" }
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
/*
|
|
||||||
* single-property.js: Sample of including a single specific properties from a package.json file
|
|
||||||
*
|
|
||||||
* (C) 2011, Charlie Robbins
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
var util = require('util'),
|
|
||||||
pkginfo = require('../lib/pkginfo')(module, 'version');
|
|
||||||
|
|
||||||
exports.someFunction = function () {
|
|
||||||
console.log('some of your custom logic here');
|
|
||||||
};
|
|
||||||
|
|
||||||
console.log('Inspecting module:');
|
|
||||||
console.dir(module.exports);
|
|
||||||
|
|
||||||
console.log('\nAll exports exposed:');
|
|
||||||
console.error(Object.keys(module.exports));
|
|
@ -1,11 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "simple-app-subdir",
|
|
||||||
"description": "A test fixture for pkginfo",
|
|
||||||
"version": "0.1.0",
|
|
||||||
"author": "Charlie Robbins <charlie.robbins@gmail.com>",
|
|
||||||
"keywords": ["test", "fixture"],
|
|
||||||
"main": "./index.js",
|
|
||||||
"scripts": { "test": "vows test/*-test.js --spec" },
|
|
||||||
"engines": { "node": ">= 0.4.0" },
|
|
||||||
"subdironly": "true"
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
/*
|
|
||||||
* multiple-properties.js: Sample of including multiple properties from a package.json file
|
|
||||||
*
|
|
||||||
* (C) 2011, Charlie Robbins
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
var util = require('util'),
|
|
||||||
path = require('path'),
|
|
||||||
pkginfo = require('../lib/pkginfo')(module, { dir: path.resolve(__dirname, 'subdir' )});
|
|
||||||
|
|
||||||
exports.someFunction = function () {
|
|
||||||
console.log('some of your custom logic here');
|
|
||||||
};
|
|
||||||
|
|
||||||
console.log('Inspecting module:');
|
|
||||||
console.dir(module.exports);
|
|
||||||
|
|
||||||
console.log('\nAll exports exposed:');
|
|
||||||
console.error(Object.keys(module.exports));
|
|
@ -1,136 +0,0 @@
|
|||||||
/*
|
|
||||||
* pkginfo.js: Top-level include for the pkginfo module
|
|
||||||
*
|
|
||||||
* (C) 2011, Charlie Robbins
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
var fs = require('fs'),
|
|
||||||
path = require('path');
|
|
||||||
|
|
||||||
//
|
|
||||||
// ### function pkginfo ([options, 'property', 'property' ..])
|
|
||||||
// #### @pmodule {Module} Parent module to read from.
|
|
||||||
// #### @options {Object|Array|string} **Optional** Options used when exposing properties.
|
|
||||||
// #### @arguments {string...} **Optional** Specified properties to expose.
|
|
||||||
// Exposes properties from the package.json file for the parent module on
|
|
||||||
// it's exports. Valid usage:
|
|
||||||
//
|
|
||||||
// `require('pkginfo')()`
|
|
||||||
//
|
|
||||||
// `require('pkginfo')('version', 'author');`
|
|
||||||
//
|
|
||||||
// `require('pkginfo')(['version', 'author']);`
|
|
||||||
//
|
|
||||||
// `require('pkginfo')({ include: ['version', 'author'] });`
|
|
||||||
//
|
|
||||||
var pkginfo = module.exports = function (pmodule, options) {
|
|
||||||
var args = [].slice.call(arguments, 2).filter(function (arg) {
|
|
||||||
return typeof arg === 'string';
|
|
||||||
});
|
|
||||||
|
|
||||||
//
|
|
||||||
// **Parse variable arguments**
|
|
||||||
//
|
|
||||||
if (Array.isArray(options)) {
|
|
||||||
//
|
|
||||||
// If the options passed in is an Array assume that
|
|
||||||
// it is the Array of properties to expose from the
|
|
||||||
// on the package.json file on the parent module.
|
|
||||||
//
|
|
||||||
options = { include: options };
|
|
||||||
}
|
|
||||||
else if (typeof options === 'string') {
|
|
||||||
//
|
|
||||||
// Otherwise if the first argument is a string, then
|
|
||||||
// assume that it is the first property to expose from
|
|
||||||
// the package.json file on the parent module.
|
|
||||||
//
|
|
||||||
options = { include: [options] };
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// **Setup default options**
|
|
||||||
//
|
|
||||||
options = options || {};
|
|
||||||
|
|
||||||
// ensure that includes have been defined
|
|
||||||
options.include = options.include || [];
|
|
||||||
|
|
||||||
if (args.length > 0) {
|
|
||||||
//
|
|
||||||
// If additional string arguments have been passed in
|
|
||||||
// then add them to the properties to expose on the
|
|
||||||
// parent module.
|
|
||||||
//
|
|
||||||
options.include = options.include.concat(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
var pkg = pkginfo.read(pmodule, options.dir).package;
|
|
||||||
Object.keys(pkg).forEach(function (key) {
|
|
||||||
if (options.include.length > 0 && !~options.include.indexOf(key)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!pmodule.exports[key]) {
|
|
||||||
pmodule.exports[key] = pkg[key];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return pkginfo;
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// ### function find (dir)
|
|
||||||
// #### @pmodule {Module} Parent module to read from.
|
|
||||||
// #### @dir {string} **Optional** Directory to start search from.
|
|
||||||
// Searches up the directory tree from `dir` until it finds a directory
|
|
||||||
// which contains a `package.json` file.
|
|
||||||
//
|
|
||||||
pkginfo.find = function (pmodule, dir) {
|
|
||||||
if (! dir) {
|
|
||||||
dir = path.dirname(pmodule.filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
var files = fs.readdirSync(dir);
|
|
||||||
|
|
||||||
if (~files.indexOf('package.json')) {
|
|
||||||
return path.join(dir, 'package.json');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dir === '/') {
|
|
||||||
throw new Error('Could not find package.json up from: ' + dir);
|
|
||||||
}
|
|
||||||
else if (!dir || dir === '.') {
|
|
||||||
throw new Error('Cannot find package.json from unspecified directory');
|
|
||||||
}
|
|
||||||
|
|
||||||
return pkginfo.find(pmodule, path.dirname(dir));
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// ### function read (pmodule, dir)
|
|
||||||
// #### @pmodule {Module} Parent module to read from.
|
|
||||||
// #### @dir {string} **Optional** Directory to start search from.
|
|
||||||
// Searches up the directory tree from `dir` until it finds a directory
|
|
||||||
// which contains a `package.json` file and returns the package information.
|
|
||||||
//
|
|
||||||
pkginfo.read = function (pmodule, dir) {
|
|
||||||
dir = pkginfo.find(pmodule, dir);
|
|
||||||
|
|
||||||
var data = fs.readFileSync(dir).toString();
|
|
||||||
|
|
||||||
return {
|
|
||||||
dir: dir,
|
|
||||||
package: JSON.parse(data)
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// Call `pkginfo` on this module and expose version.
|
|
||||||
//
|
|
||||||
pkginfo(module, {
|
|
||||||
dir: __dirname,
|
|
||||||
include: ['version'],
|
|
||||||
target: pkginfo
|
|
||||||
});
|
|
@ -1,54 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "pkginfo",
|
|
||||||
"version": "0.3.0",
|
|
||||||
"description": "An easy way to expose properties on a module from a package.json",
|
|
||||||
"author": {
|
|
||||||
"name": "Charlie Robbins",
|
|
||||||
"email": "charlie.robbins@gmail.com"
|
|
||||||
},
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "http://github.com/indexzero/node-pkginfo.git"
|
|
||||||
},
|
|
||||||
"keywords": [
|
|
||||||
"info",
|
|
||||||
"tools",
|
|
||||||
"package.json"
|
|
||||||
],
|
|
||||||
"devDependencies": {
|
|
||||||
"vows": "0.7.x"
|
|
||||||
},
|
|
||||||
"main": "./lib/pkginfo",
|
|
||||||
"scripts": {
|
|
||||||
"test": "vows test/*-test.js --spec"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 0.4.0"
|
|
||||||
},
|
|
||||||
"readme": "# node-pkginfo\n\nAn easy way to expose properties on a module from a package.json\n\n## Installation\n\n### Installing npm (node package manager)\n```\n curl http://npmjs.org/install.sh | sh\n```\n\n### Installing pkginfo\n```\n [sudo] npm install pkginfo\n```\n\n## Motivation\nHow often when writing node.js modules have you written the following line(s) of code? \n\n* Hard code your version string into your code\n\n``` js\n exports.version = '0.1.0';\n```\n\n* Programmatically expose the version from the package.json\n\n``` js\n exports.version = JSON.parse(fs.readFileSync('/path/to/package.json', 'utf8')).version;\n```\n\nIn other words, how often have you wanted to expose basic information from your package.json onto your module programmatically? **WELL NOW YOU CAN!**\n\n## Usage\n\nUsing `pkginfo` is idiot-proof, just require and invoke it. \n\n``` js\n var pkginfo = require('pkginfo')(module);\n \n console.dir(module.exports);\n```\n\nBy invoking the `pkginfo` module all of the properties in your `package.json` file will be automatically exposed on the callee module (i.e. the parent module of `pkginfo`). \n\nHere's a sample of the output:\n\n```\n { name: 'simple-app',\n description: 'A test fixture for pkginfo',\n version: '0.1.0',\n author: 'Charlie Robbins <charlie.robbins@gmail.com>',\n keywords: [ 'test', 'fixture' ],\n main: './index.js',\n scripts: { test: 'vows test/*-test.js --spec' },\n engines: { node: '>= 0.4.0' } }\n```\n\n### Expose specific properties\nIf you don't want to expose **all** properties on from your `package.json` on your module then simple pass those properties to the `pkginfo` function:\n\n``` js\n var pkginfo = require('pkginfo')(module, 'version', 'author');\n \n console.dir(module.exports);\n```\n\n```\n { version: '0.1.0',\n author: 'Charlie Robbins <charlie.robbins@gmail.com>' }\n```\n\nIf you're looking for further usage see the [examples][0] included in this repository. \n\n## Run Tests\nTests are written in [vows][1] and give complete coverage of all APIs.\n\n```\n vows test/*-test.js --spec\n```\n\n[0]: https://github.com/indexzero/node-pkginfo/tree/master/examples\n[1]: http://vowsjs.org\n\n#### Author: [Charlie Robbins](http://nodejitsu.com)\n#### License: MIT",
|
|
||||||
"readmeFilename": "README.md",
|
|
||||||
"_id": "pkginfo@0.3.0",
|
|
||||||
"dist": {
|
|
||||||
"shasum": "726411401039fe9b009eea86614295d5f3a54276",
|
|
||||||
"tarball": "http://registry.npmjs.org/pkginfo/-/pkginfo-0.3.0.tgz"
|
|
||||||
},
|
|
||||||
"_npmVersion": "1.1.66",
|
|
||||||
"_npmUser": {
|
|
||||||
"name": "indexzero",
|
|
||||||
"email": "charlie.robbins@gmail.com"
|
|
||||||
},
|
|
||||||
"maintainers": [
|
|
||||||
{
|
|
||||||
"name": "indexzero",
|
|
||||||
"email": "charlie.robbins@gmail.com"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"directories": {},
|
|
||||||
"_shasum": "726411401039fe9b009eea86614295d5f3a54276",
|
|
||||||
"_from": "pkginfo@0.x.x",
|
|
||||||
"_resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.3.0.tgz",
|
|
||||||
"bugs": {
|
|
||||||
"url": "https://github.com/indexzero/node-pkginfo/issues"
|
|
||||||
},
|
|
||||||
"homepage": "https://github.com/indexzero/node-pkginfo"
|
|
||||||
}
|
|
@ -1,83 +0,0 @@
|
|||||||
/*
|
|
||||||
* pkginfo-test.js: Tests for the pkginfo module.
|
|
||||||
*
|
|
||||||
* (C) 2011, Charlie Robbins
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
var assert = require('assert'),
|
|
||||||
exec = require('child_process').exec,
|
|
||||||
fs = require('fs'),
|
|
||||||
path = require('path'),
|
|
||||||
vows = require('vows'),
|
|
||||||
pkginfo = require('../lib/pkginfo');
|
|
||||||
|
|
||||||
function assertProperties (source, target) {
|
|
||||||
assert.lengthOf(source, target.length + 1);
|
|
||||||
target.forEach(function (prop) {
|
|
||||||
assert.isTrue(!!~source.indexOf(prop));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function compareWithExample(targetPath) {
|
|
||||||
var examplePaths = ['package.json'];
|
|
||||||
|
|
||||||
if (targetPath) {
|
|
||||||
examplePaths.unshift(targetPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
return function(exposed) {
|
|
||||||
var pkg = fs.readFileSync(path.join.apply(null, [__dirname, '..', 'examples'].concat(examplePaths))).toString(),
|
|
||||||
keys = Object.keys(JSON.parse(pkg));
|
|
||||||
|
|
||||||
assertProperties(exposed, keys);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function testExposes (options) {
|
|
||||||
return {
|
|
||||||
topic: function () {
|
|
||||||
exec('node ' + path.join(__dirname, '..', 'examples', options.script), this.callback);
|
|
||||||
},
|
|
||||||
"should expose that property correctly": function (err, stdout, stderr) {
|
|
||||||
assert.isNull(err);
|
|
||||||
|
|
||||||
var exposed = stderr.match(/'(\w+)'/ig).map(function (p) {
|
|
||||||
return p.substring(1, p.length - 1);
|
|
||||||
});
|
|
||||||
|
|
||||||
return !options.assert
|
|
||||||
? assertProperties(exposed, options.properties)
|
|
||||||
: options.assert(exposed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
vows.describe('pkginfo').addBatch({
|
|
||||||
"When using the pkginfo module": {
|
|
||||||
"and passed a single `string` argument": testExposes({
|
|
||||||
script: 'single-property.js',
|
|
||||||
properties: ['version']
|
|
||||||
}),
|
|
||||||
"and passed multiple `string` arguments": testExposes({
|
|
||||||
script: 'multiple-properties.js',
|
|
||||||
properties: ['version', 'author']
|
|
||||||
}),
|
|
||||||
"and passed an `object` argument": testExposes({
|
|
||||||
script: 'object-argument.js',
|
|
||||||
properties: ['version', 'author']
|
|
||||||
}),
|
|
||||||
"and passed an `array` argument": testExposes({
|
|
||||||
script: 'array-argument.js',
|
|
||||||
properties: ['version', 'author']
|
|
||||||
}),
|
|
||||||
"and read from a specified directory": testExposes({
|
|
||||||
script: 'target-dir.js',
|
|
||||||
assert: compareWithExample('subdir')
|
|
||||||
}),
|
|
||||||
"and passed no arguments": testExposes({
|
|
||||||
script: 'all-properties.js',
|
|
||||||
assert: compareWithExample()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}).export(module);
|
|
@ -1,2 +0,0 @@
|
|||||||
npm-debug.log
|
|
||||||
node_modules
|
|
@ -1,25 +0,0 @@
|
|||||||
Copyright (c) Isaac Z. Schlueter
|
|
||||||
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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
|
|
@ -1,15 +0,0 @@
|
|||||||
The ISC License
|
|
||||||
|
|
||||||
Copyright (c) Isaac Z. Schlueter and Contributors
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
||||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
|
||||||
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
@ -1,53 +0,0 @@
|
|||||||
## read
|
|
||||||
|
|
||||||
For reading user input from stdin.
|
|
||||||
|
|
||||||
Similar to the `readline` builtin's `question()` method, but with a
|
|
||||||
few more features.
|
|
||||||
|
|
||||||
## USAGE
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
var read = require("read")
|
|
||||||
read(options, callback)
|
|
||||||
```
|
|
||||||
|
|
||||||
The callback gets called with either the user input, or the default
|
|
||||||
specified, or an error, as `callback(error, result, isDefault)`
|
|
||||||
node style.
|
|
||||||
|
|
||||||
## OPTIONS
|
|
||||||
|
|
||||||
Every option is optional.
|
|
||||||
|
|
||||||
* `prompt` What to write to stdout before reading input.
|
|
||||||
* `silent` Don't echo the output as the user types it.
|
|
||||||
* `replace` Replace silenced characters with the supplied character value.
|
|
||||||
* `timeout` Number of ms to wait for user input before giving up.
|
|
||||||
* `default` The default value if the user enters nothing.
|
|
||||||
* `edit` Allow the user to edit the default value.
|
|
||||||
* `terminal` Treat the output as a TTY, whether it is or not.
|
|
||||||
* `input` Readable stream to get input data from. (default `process.stdin`)
|
|
||||||
* `output` Writeable stream to write prompts to. (default: `process.stdout`)
|
|
||||||
|
|
||||||
If silent is true, and the input is a TTY, then read will set raw
|
|
||||||
mode, and read character by character.
|
|
||||||
|
|
||||||
## COMPATIBILITY
|
|
||||||
|
|
||||||
This module works sort of with node 0.6. It does not work with node
|
|
||||||
versions less than 0.6. It is best on node 0.8.
|
|
||||||
|
|
||||||
On node version 0.6, it will remove all listeners on the input
|
|
||||||
stream's `data` and `keypress` events, because the readline module did
|
|
||||||
not fully clean up after itself in that version of node, and did not
|
|
||||||
make it possible to clean up after it in a way that has no potential
|
|
||||||
for side effects.
|
|
||||||
|
|
||||||
Additionally, some of the readline options (like `terminal`) will not
|
|
||||||
function in versions of node before 0.8, because they were not
|
|
||||||
implemented in the builtin readline module.
|
|
||||||
|
|
||||||
## CONTRIBUTING
|
|
||||||
|
|
||||||
Patches welcome.
|
|
@ -1,13 +0,0 @@
|
|||||||
var read = require("../lib/read.js")
|
|
||||||
|
|
||||||
read({prompt: "Username: ", default: "test-user" }, function (er, user) {
|
|
||||||
read({prompt: "Password: ", default: "test-pass", silent: true }, function (er, pass) {
|
|
||||||
read({prompt: "Password again: ", default: "test-pass", silent: true }, function (er, pass2) {
|
|
||||||
console.error({user: user,
|
|
||||||
pass: pass,
|
|
||||||
verify: pass2,
|
|
||||||
passMatch: (pass === pass2)})
|
|
||||||
console.error("the program should exit now")
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
@ -1,113 +0,0 @@
|
|||||||
|
|
||||||
module.exports = read
|
|
||||||
|
|
||||||
var readline = require('readline')
|
|
||||||
var Mute = require('mute-stream')
|
|
||||||
|
|
||||||
function read (opts, cb) {
|
|
||||||
if (opts.num) {
|
|
||||||
throw new Error('read() no longer accepts a char number limit')
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof opts.default !== 'undefined' &&
|
|
||||||
typeof opts.default !== 'string' &&
|
|
||||||
typeof opts.default !== 'number') {
|
|
||||||
throw new Error('default value must be string or number')
|
|
||||||
}
|
|
||||||
|
|
||||||
var input = opts.input || process.stdin
|
|
||||||
var output = opts.output || process.stdout
|
|
||||||
var prompt = (opts.prompt || '').trim() + ' '
|
|
||||||
var silent = opts.silent
|
|
||||||
var editDef = false
|
|
||||||
var timeout = opts.timeout
|
|
||||||
|
|
||||||
var def = opts.default || ''
|
|
||||||
if (def) {
|
|
||||||
if (silent) {
|
|
||||||
prompt += '(<default hidden>) '
|
|
||||||
} else if (opts.edit) {
|
|
||||||
editDef = true
|
|
||||||
} else {
|
|
||||||
prompt += '(' + def + ') '
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var terminal = !!(opts.terminal || output.isTTY)
|
|
||||||
|
|
||||||
var m = new Mute({ replace: opts.replace, prompt: prompt })
|
|
||||||
m.pipe(output, {end: false})
|
|
||||||
output = m
|
|
||||||
var rlOpts = { input: input, output: output, terminal: terminal }
|
|
||||||
|
|
||||||
if (process.version.match(/^v0\.6/)) {
|
|
||||||
var rl = readline.createInterface(rlOpts.input, rlOpts.output)
|
|
||||||
} else {
|
|
||||||
var rl = readline.createInterface(rlOpts)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
output.unmute()
|
|
||||||
rl.setPrompt(prompt)
|
|
||||||
rl.prompt()
|
|
||||||
if (silent) {
|
|
||||||
output.mute()
|
|
||||||
} else if (editDef) {
|
|
||||||
rl.line = def
|
|
||||||
rl.cursor = def.length
|
|
||||||
rl._refreshLine()
|
|
||||||
}
|
|
||||||
|
|
||||||
var called = false
|
|
||||||
rl.on('line', onLine)
|
|
||||||
rl.on('error', onError)
|
|
||||||
|
|
||||||
rl.on('SIGINT', function () {
|
|
||||||
rl.close()
|
|
||||||
onError(new Error('canceled'))
|
|
||||||
})
|
|
||||||
|
|
||||||
var timer
|
|
||||||
if (timeout) {
|
|
||||||
timer = setTimeout(function () {
|
|
||||||
onError(new Error('timed out'))
|
|
||||||
}, timeout)
|
|
||||||
}
|
|
||||||
|
|
||||||
function done () {
|
|
||||||
called = true
|
|
||||||
rl.close()
|
|
||||||
|
|
||||||
if (process.version.match(/^v0\.6/)) {
|
|
||||||
rl.input.removeAllListeners('data')
|
|
||||||
rl.input.removeAllListeners('keypress')
|
|
||||||
rl.input.pause()
|
|
||||||
}
|
|
||||||
|
|
||||||
clearTimeout(timer)
|
|
||||||
output.mute()
|
|
||||||
output.end()
|
|
||||||
}
|
|
||||||
|
|
||||||
function onError (er) {
|
|
||||||
if (called) return
|
|
||||||
done()
|
|
||||||
return cb(er)
|
|
||||||
}
|
|
||||||
|
|
||||||
function onLine (line) {
|
|
||||||
if (called) return
|
|
||||||
if (silent && terminal) {
|
|
||||||
output.unmute()
|
|
||||||
output.write('\r\n')
|
|
||||||
}
|
|
||||||
done()
|
|
||||||
// truncate the \n at the end.
|
|
||||||
line = line.replace(/\r?\n$/, '')
|
|
||||||
var isDefault = !!(editDef && line === def)
|
|
||||||
if (def && !line) {
|
|
||||||
isDefault = true
|
|
||||||
line = def
|
|
||||||
}
|
|
||||||
cb(null, line, isDefault)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
The ISC License
|
|
||||||
|
|
||||||
Copyright (c) Isaac Z. Schlueter and Contributors
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
||||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
|
||||||
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
@ -1,68 +0,0 @@
|
|||||||
# mute-stream
|
|
||||||
|
|
||||||
Bytes go in, but they don't come out (when muted).
|
|
||||||
|
|
||||||
This is a basic pass-through stream, but when muted, the bytes are
|
|
||||||
silently dropped, rather than being passed through.
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
var MuteStream = require('mute-stream')
|
|
||||||
|
|
||||||
var ms = new MuteStream(options)
|
|
||||||
|
|
||||||
ms.pipe(process.stdout)
|
|
||||||
ms.write('foo') // writes 'foo' to stdout
|
|
||||||
ms.mute()
|
|
||||||
ms.write('bar') // does not write 'bar'
|
|
||||||
ms.unmute()
|
|
||||||
ms.write('baz') // writes 'baz' to stdout
|
|
||||||
|
|
||||||
// can also be used to mute incoming data
|
|
||||||
var ms = new MuteStream
|
|
||||||
input.pipe(ms)
|
|
||||||
|
|
||||||
ms.on('data', function (c) {
|
|
||||||
console.log('data: ' + c)
|
|
||||||
})
|
|
||||||
|
|
||||||
input.emit('data', 'foo') // logs 'foo'
|
|
||||||
ms.mute()
|
|
||||||
input.emit('data', 'bar') // does not log 'bar'
|
|
||||||
ms.unmute()
|
|
||||||
input.emit('data', 'baz') // logs 'baz'
|
|
||||||
```
|
|
||||||
|
|
||||||
## Options
|
|
||||||
|
|
||||||
All options are optional.
|
|
||||||
|
|
||||||
* `replace` Set to a string to replace each character with the
|
|
||||||
specified string when muted. (So you can show `****` instead of the
|
|
||||||
password, for example.)
|
|
||||||
|
|
||||||
* `prompt` If you are using a replacement char, and also using a
|
|
||||||
prompt with a readline stream (as for a `Password: *****` input),
|
|
||||||
then specify what the prompt is so that backspace will work
|
|
||||||
properly. Otherwise, pressing backspace will overwrite the prompt
|
|
||||||
with the replacement character, which is weird.
|
|
||||||
|
|
||||||
## ms.mute()
|
|
||||||
|
|
||||||
Set `muted` to `true`. Turns `.write()` into a no-op.
|
|
||||||
|
|
||||||
## ms.unmute()
|
|
||||||
|
|
||||||
Set `muted` to `false`
|
|
||||||
|
|
||||||
## ms.isTTY
|
|
||||||
|
|
||||||
True if the pipe destination is a TTY, or if the incoming pipe source is
|
|
||||||
a TTY.
|
|
||||||
|
|
||||||
## Other stream methods...
|
|
||||||
|
|
||||||
The other standard readable and writable stream methods are all
|
|
||||||
available. The MuteStream object acts as a facade to its pipe source
|
|
||||||
and destination.
|
|
@ -1,140 +0,0 @@
|
|||||||
var Stream = require('stream')
|
|
||||||
|
|
||||||
module.exports = MuteStream
|
|
||||||
|
|
||||||
// var out = new MuteStream(process.stdout)
|
|
||||||
// argument auto-pipes
|
|
||||||
function MuteStream (opts) {
|
|
||||||
Stream.apply(this)
|
|
||||||
opts = opts || {}
|
|
||||||
this.writable = this.readable = true
|
|
||||||
this.muted = false
|
|
||||||
this.on('pipe', this._onpipe)
|
|
||||||
this.replace = opts.replace
|
|
||||||
|
|
||||||
// For readline-type situations
|
|
||||||
// This much at the start of a line being redrawn after a ctrl char
|
|
||||||
// is seen (such as backspace) won't be redrawn as the replacement
|
|
||||||
this._prompt = opts.prompt || null
|
|
||||||
this._hadControl = false
|
|
||||||
}
|
|
||||||
|
|
||||||
MuteStream.prototype = Object.create(Stream.prototype)
|
|
||||||
|
|
||||||
Object.defineProperty(MuteStream.prototype, 'constructor', {
|
|
||||||
value: MuteStream,
|
|
||||||
enumerable: false
|
|
||||||
})
|
|
||||||
|
|
||||||
MuteStream.prototype.mute = function () {
|
|
||||||
this.muted = true
|
|
||||||
}
|
|
||||||
|
|
||||||
MuteStream.prototype.unmute = function () {
|
|
||||||
this.muted = false
|
|
||||||
}
|
|
||||||
|
|
||||||
Object.defineProperty(MuteStream.prototype, '_onpipe', {
|
|
||||||
value: onPipe,
|
|
||||||
enumerable: false,
|
|
||||||
writable: true,
|
|
||||||
configurable: true
|
|
||||||
})
|
|
||||||
|
|
||||||
function onPipe (src) {
|
|
||||||
this._src = src
|
|
||||||
}
|
|
||||||
|
|
||||||
Object.defineProperty(MuteStream.prototype, 'isTTY', {
|
|
||||||
get: getIsTTY,
|
|
||||||
set: setIsTTY,
|
|
||||||
enumerable: true,
|
|
||||||
configurable: true
|
|
||||||
})
|
|
||||||
|
|
||||||
function getIsTTY () {
|
|
||||||
return( (this._dest) ? this._dest.isTTY
|
|
||||||
: (this._src) ? this._src.isTTY
|
|
||||||
: false
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// basically just get replace the getter/setter with a regular value
|
|
||||||
function setIsTTY (isTTY) {
|
|
||||||
Object.defineProperty(this, 'isTTY', {
|
|
||||||
value: isTTY,
|
|
||||||
enumerable: true,
|
|
||||||
writable: true,
|
|
||||||
configurable: true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
Object.defineProperty(MuteStream.prototype, 'rows', {
|
|
||||||
get: function () {
|
|
||||||
return( this._dest ? this._dest.rows
|
|
||||||
: this._src ? this._src.rows
|
|
||||||
: undefined )
|
|
||||||
}, enumerable: true, configurable: true })
|
|
||||||
|
|
||||||
Object.defineProperty(MuteStream.prototype, 'columns', {
|
|
||||||
get: function () {
|
|
||||||
return( this._dest ? this._dest.columns
|
|
||||||
: this._src ? this._src.columns
|
|
||||||
: undefined )
|
|
||||||
}, enumerable: true, configurable: true })
|
|
||||||
|
|
||||||
|
|
||||||
MuteStream.prototype.pipe = function (dest) {
|
|
||||||
this._dest = dest
|
|
||||||
return Stream.prototype.pipe.call(this, dest)
|
|
||||||
}
|
|
||||||
|
|
||||||
MuteStream.prototype.pause = function () {
|
|
||||||
if (this._src) return this._src.pause()
|
|
||||||
}
|
|
||||||
|
|
||||||
MuteStream.prototype.resume = function () {
|
|
||||||
if (this._src) return this._src.resume()
|
|
||||||
}
|
|
||||||
|
|
||||||
MuteStream.prototype.write = function (c) {
|
|
||||||
if (this.muted) {
|
|
||||||
if (!this.replace) return true
|
|
||||||
if (c.match(/^\u001b/)) {
|
|
||||||
this._hadControl = true
|
|
||||||
return this.emit('data', c)
|
|
||||||
} else {
|
|
||||||
if (this._prompt && this._hadControl &&
|
|
||||||
c.indexOf(this._prompt) === 0) {
|
|
||||||
this._hadControl = false
|
|
||||||
this.emit('data', this._prompt)
|
|
||||||
c = c.substr(this._prompt.length)
|
|
||||||
}
|
|
||||||
c = c.toString().replace(/./g, this.replace)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.emit('data', c)
|
|
||||||
}
|
|
||||||
|
|
||||||
MuteStream.prototype.end = function (c) {
|
|
||||||
if (this.muted) {
|
|
||||||
if (c && this.replace) {
|
|
||||||
c = c.toString().replace(/./g, this.replace)
|
|
||||||
} else {
|
|
||||||
c = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (c) this.emit('data', c)
|
|
||||||
this.emit('end')
|
|
||||||
}
|
|
||||||
|
|
||||||
function proxy (fn) { return function () {
|
|
||||||
var d = this._dest
|
|
||||||
var s = this._src
|
|
||||||
if (d && d[fn]) d[fn].apply(d, arguments)
|
|
||||||
if (s && s[fn]) s[fn].apply(s, arguments)
|
|
||||||
}}
|
|
||||||
|
|
||||||
MuteStream.prototype.destroy = proxy('destroy')
|
|
||||||
MuteStream.prototype.destroySoon = proxy('destroySoon')
|
|
||||||
MuteStream.prototype.close = proxy('close')
|
|
@ -1,56 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "mute-stream",
|
|
||||||
"version": "0.0.5",
|
|
||||||
"main": "mute.js",
|
|
||||||
"directories": {
|
|
||||||
"test": "test"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"tap": "~0.2.5"
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"test": "tap test/*.js"
|
|
||||||
},
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "git://github.com/isaacs/mute-stream.git"
|
|
||||||
},
|
|
||||||
"keywords": [
|
|
||||||
"mute",
|
|
||||||
"stream",
|
|
||||||
"pipe"
|
|
||||||
],
|
|
||||||
"author": {
|
|
||||||
"name": "Isaac Z. Schlueter",
|
|
||||||
"email": "i@izs.me",
|
|
||||||
"url": "http://blog.izs.me/"
|
|
||||||
},
|
|
||||||
"license": "ISC",
|
|
||||||
"description": "Bytes go in, but they don't come out (when muted).",
|
|
||||||
"gitHead": "17d9854a315f56088d039534f87b740e470a9af0",
|
|
||||||
"bugs": {
|
|
||||||
"url": "https://github.com/isaacs/mute-stream/issues"
|
|
||||||
},
|
|
||||||
"homepage": "https://github.com/isaacs/mute-stream#readme",
|
|
||||||
"_id": "mute-stream@0.0.5",
|
|
||||||
"_shasum": "8fbfabb0a98a253d3184331f9e8deb7372fac6c0",
|
|
||||||
"_from": "mute-stream@~0.0.4",
|
|
||||||
"_npmVersion": "2.10.0",
|
|
||||||
"_nodeVersion": "2.0.1",
|
|
||||||
"_npmUser": {
|
|
||||||
"name": "isaacs",
|
|
||||||
"email": "isaacs@npmjs.com"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"shasum": "8fbfabb0a98a253d3184331f9e8deb7372fac6c0",
|
|
||||||
"tarball": "http://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz"
|
|
||||||
},
|
|
||||||
"maintainers": [
|
|
||||||
{
|
|
||||||
"name": "isaacs",
|
|
||||||
"email": "i@izs.me"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"_resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz",
|
|
||||||
"readme": "ERROR: No README data found!"
|
|
||||||
}
|
|
@ -1,207 +0,0 @@
|
|||||||
var Stream = require('stream')
|
|
||||||
var tap = require('tap')
|
|
||||||
var MS = require('../mute.js')
|
|
||||||
|
|
||||||
// some marker objects
|
|
||||||
var END = {}
|
|
||||||
var PAUSE = {}
|
|
||||||
var RESUME = {}
|
|
||||||
|
|
||||||
function PassThrough () {
|
|
||||||
Stream.call(this)
|
|
||||||
this.readable = this.writable = true
|
|
||||||
}
|
|
||||||
|
|
||||||
PassThrough.prototype = Object.create(Stream.prototype, {
|
|
||||||
constructor: {
|
|
||||||
value: PassThrough
|
|
||||||
},
|
|
||||||
write: {
|
|
||||||
value: function (c) {
|
|
||||||
this.emit('data', c)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
end: {
|
|
||||||
value: function (c) {
|
|
||||||
if (c) this.write(c)
|
|
||||||
this.emit('end')
|
|
||||||
}
|
|
||||||
},
|
|
||||||
pause: {
|
|
||||||
value: function () {
|
|
||||||
this.emit('pause')
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resume: {
|
|
||||||
value: function () {
|
|
||||||
this.emit('resume')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
tap.test('incoming', function (t) {
|
|
||||||
var ms = new MS
|
|
||||||
var str = new PassThrough
|
|
||||||
str.pipe(ms)
|
|
||||||
|
|
||||||
var expect = ['foo', 'boo', END]
|
|
||||||
ms.on('data', function (c) {
|
|
||||||
t.equal(c, expect.shift())
|
|
||||||
})
|
|
||||||
ms.on('end', function () {
|
|
||||||
t.equal(END, expect.shift())
|
|
||||||
t.end()
|
|
||||||
})
|
|
||||||
str.write('foo')
|
|
||||||
ms.mute()
|
|
||||||
str.write('bar')
|
|
||||||
ms.unmute()
|
|
||||||
str.write('boo')
|
|
||||||
ms.mute()
|
|
||||||
str.write('blaz')
|
|
||||||
str.end('grelb')
|
|
||||||
})
|
|
||||||
|
|
||||||
tap.test('outgoing', function (t) {
|
|
||||||
var ms = new MS
|
|
||||||
var str = new PassThrough
|
|
||||||
ms.pipe(str)
|
|
||||||
|
|
||||||
var expect = ['foo', 'boo', END]
|
|
||||||
str.on('data', function (c) {
|
|
||||||
t.equal(c, expect.shift())
|
|
||||||
})
|
|
||||||
str.on('end', function () {
|
|
||||||
t.equal(END, expect.shift())
|
|
||||||
t.end()
|
|
||||||
})
|
|
||||||
|
|
||||||
ms.write('foo')
|
|
||||||
ms.mute()
|
|
||||||
ms.write('bar')
|
|
||||||
ms.unmute()
|
|
||||||
ms.write('boo')
|
|
||||||
ms.mute()
|
|
||||||
ms.write('blaz')
|
|
||||||
ms.end('grelb')
|
|
||||||
})
|
|
||||||
|
|
||||||
tap.test('isTTY', function (t) {
|
|
||||||
var str = new PassThrough
|
|
||||||
str.isTTY = true
|
|
||||||
str.columns=80
|
|
||||||
str.rows=24
|
|
||||||
|
|
||||||
var ms = new MS
|
|
||||||
t.equal(ms.isTTY, false)
|
|
||||||
t.equal(ms.columns, undefined)
|
|
||||||
t.equal(ms.rows, undefined)
|
|
||||||
ms.pipe(str)
|
|
||||||
t.equal(ms.isTTY, true)
|
|
||||||
t.equal(ms.columns, 80)
|
|
||||||
t.equal(ms.rows, 24)
|
|
||||||
str.isTTY = false
|
|
||||||
t.equal(ms.isTTY, false)
|
|
||||||
t.equal(ms.columns, 80)
|
|
||||||
t.equal(ms.rows, 24)
|
|
||||||
str.isTTY = true
|
|
||||||
t.equal(ms.isTTY, true)
|
|
||||||
t.equal(ms.columns, 80)
|
|
||||||
t.equal(ms.rows, 24)
|
|
||||||
ms.isTTY = false
|
|
||||||
t.equal(ms.isTTY, false)
|
|
||||||
t.equal(ms.columns, 80)
|
|
||||||
t.equal(ms.rows, 24)
|
|
||||||
|
|
||||||
ms = new MS
|
|
||||||
t.equal(ms.isTTY, false)
|
|
||||||
str.pipe(ms)
|
|
||||||
t.equal(ms.isTTY, true)
|
|
||||||
str.isTTY = false
|
|
||||||
t.equal(ms.isTTY, false)
|
|
||||||
str.isTTY = true
|
|
||||||
t.equal(ms.isTTY, true)
|
|
||||||
ms.isTTY = false
|
|
||||||
t.equal(ms.isTTY, false)
|
|
||||||
|
|
||||||
t.end()
|
|
||||||
})
|
|
||||||
|
|
||||||
tap.test('pause/resume incoming', function (t) {
|
|
||||||
var str = new PassThrough
|
|
||||||
var ms = new MS
|
|
||||||
str.on('pause', function () {
|
|
||||||
t.equal(PAUSE, expect.shift())
|
|
||||||
})
|
|
||||||
str.on('resume', function () {
|
|
||||||
t.equal(RESUME, expect.shift())
|
|
||||||
})
|
|
||||||
var expect = [PAUSE, RESUME, PAUSE, RESUME]
|
|
||||||
str.pipe(ms)
|
|
||||||
ms.pause()
|
|
||||||
ms.resume()
|
|
||||||
ms.pause()
|
|
||||||
ms.resume()
|
|
||||||
t.equal(expect.length, 0, 'saw all events')
|
|
||||||
t.end()
|
|
||||||
})
|
|
||||||
|
|
||||||
tap.test('replace with *', function (t) {
|
|
||||||
var str = new PassThrough
|
|
||||||
var ms = new MS({replace: '*'})
|
|
||||||
str.pipe(ms)
|
|
||||||
var expect = ['foo', '*****', 'bar', '***', 'baz', 'boo', '**', '****']
|
|
||||||
|
|
||||||
ms.on('data', function (c) {
|
|
||||||
t.equal(c, expect.shift())
|
|
||||||
})
|
|
||||||
|
|
||||||
str.write('foo')
|
|
||||||
ms.mute()
|
|
||||||
str.write('12345')
|
|
||||||
ms.unmute()
|
|
||||||
str.write('bar')
|
|
||||||
ms.mute()
|
|
||||||
str.write('baz')
|
|
||||||
ms.unmute()
|
|
||||||
str.write('baz')
|
|
||||||
str.write('boo')
|
|
||||||
ms.mute()
|
|
||||||
str.write('xy')
|
|
||||||
str.write('xyzΩ')
|
|
||||||
|
|
||||||
t.equal(expect.length, 0)
|
|
||||||
t.end()
|
|
||||||
})
|
|
||||||
|
|
||||||
tap.test('replace with ~YARG~', function (t) {
|
|
||||||
var str = new PassThrough
|
|
||||||
var ms = new MS({replace: '~YARG~'})
|
|
||||||
str.pipe(ms)
|
|
||||||
var expect = ['foo', '~YARG~~YARG~~YARG~~YARG~~YARG~', 'bar',
|
|
||||||
'~YARG~~YARG~~YARG~', 'baz', 'boo', '~YARG~~YARG~',
|
|
||||||
'~YARG~~YARG~~YARG~~YARG~']
|
|
||||||
|
|
||||||
ms.on('data', function (c) {
|
|
||||||
t.equal(c, expect.shift())
|
|
||||||
})
|
|
||||||
|
|
||||||
// also throw some unicode in there, just for good measure.
|
|
||||||
str.write('foo')
|
|
||||||
ms.mute()
|
|
||||||
str.write('ΩΩ')
|
|
||||||
ms.unmute()
|
|
||||||
str.write('bar')
|
|
||||||
ms.mute()
|
|
||||||
str.write('Ω')
|
|
||||||
ms.unmute()
|
|
||||||
str.write('baz')
|
|
||||||
str.write('boo')
|
|
||||||
ms.mute()
|
|
||||||
str.write('Ω')
|
|
||||||
str.write('ΩΩ')
|
|
||||||
|
|
||||||
t.equal(expect.length, 0)
|
|
||||||
t.end()
|
|
||||||
})
|
|
@ -1,55 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "read",
|
|
||||||
"version": "1.0.6",
|
|
||||||
"main": "lib/read.js",
|
|
||||||
"dependencies": {
|
|
||||||
"mute-stream": "~0.0.4"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"tap": "*"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=0.8"
|
|
||||||
},
|
|
||||||
"author": {
|
|
||||||
"name": "Isaac Z. Schlueter",
|
|
||||||
"email": "i@izs.me",
|
|
||||||
"url": "http://blog.izs.me/"
|
|
||||||
},
|
|
||||||
"description": "read(1) for node programs",
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "git://github.com/isaacs/read.git"
|
|
||||||
},
|
|
||||||
"license": "ISC",
|
|
||||||
"scripts": {
|
|
||||||
"test": "tap test/*.js"
|
|
||||||
},
|
|
||||||
"gitHead": "2f5101c8e41332a033e5aa4e27e33fd6e09598e2",
|
|
||||||
"bugs": {
|
|
||||||
"url": "https://github.com/isaacs/read/issues"
|
|
||||||
},
|
|
||||||
"homepage": "https://github.com/isaacs/read#readme",
|
|
||||||
"_id": "read@1.0.6",
|
|
||||||
"_shasum": "09873c14ecc114d063fad43b8ca5a33d304721c8",
|
|
||||||
"_from": "read@1.0.x",
|
|
||||||
"_npmVersion": "2.10.0",
|
|
||||||
"_nodeVersion": "2.0.1",
|
|
||||||
"_npmUser": {
|
|
||||||
"name": "isaacs",
|
|
||||||
"email": "isaacs@npmjs.com"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"shasum": "09873c14ecc114d063fad43b8ca5a33d304721c8",
|
|
||||||
"tarball": "http://registry.npmjs.org/read/-/read-1.0.6.tgz"
|
|
||||||
},
|
|
||||||
"maintainers": [
|
|
||||||
{
|
|
||||||
"name": "isaacs",
|
|
||||||
"email": "i@izs.me"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"directories": {},
|
|
||||||
"_resolved": "https://registry.npmjs.org/read/-/read-1.0.6.tgz",
|
|
||||||
"readme": "ERROR: No README data found!"
|
|
||||||
}
|
|
@ -1,4 +0,0 @@
|
|||||||
var read = require('read');
|
|
||||||
read({ silent: true, prompt: 'stars: ' }, function(er, data) {
|
|
||||||
console.log(er, data)
|
|
||||||
})
|
|
@ -1,60 +0,0 @@
|
|||||||
var tap = require('tap')
|
|
||||||
var read = require('../lib/read.js')
|
|
||||||
|
|
||||||
if (process.argv[2] === 'child') {
|
|
||||||
return child()
|
|
||||||
}
|
|
||||||
|
|
||||||
var CLOSE = 'close'
|
|
||||||
if (process.version.match(/^v0\.6/)) {
|
|
||||||
CLOSE = 'exit'
|
|
||||||
}
|
|
||||||
|
|
||||||
var spawn = require('child_process').spawn
|
|
||||||
|
|
||||||
tap.test('basic', function (t) {
|
|
||||||
var child = spawn(process.execPath, [__filename, 'child'])
|
|
||||||
var output = ''
|
|
||||||
var write = child.stdin.write.bind(child.stdin)
|
|
||||||
child.stdout.on('data', function (c) {
|
|
||||||
console.error('data %s', c)
|
|
||||||
output += c
|
|
||||||
if (output.match(/Username: \(test-user\) $/)) {
|
|
||||||
process.nextTick(write.bind(null, 'a user\n'))
|
|
||||||
} else if (output.match(/Password: \(<default hidden>\) $/)) {
|
|
||||||
process.nextTick(write.bind(null, 'a password\n'))
|
|
||||||
} else if (output.match(/Password again: \(<default hidden>\) $/)) {
|
|
||||||
process.nextTick(write.bind(null, 'a password\n'))
|
|
||||||
} else {
|
|
||||||
console.error('prompts done, output=%j', output)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
var result = ''
|
|
||||||
child.stderr.on('data', function (c) {
|
|
||||||
result += c
|
|
||||||
console.error('result %j', c.toString())
|
|
||||||
})
|
|
||||||
|
|
||||||
child.on(CLOSE, function () {
|
|
||||||
result = JSON.parse(result)
|
|
||||||
t.same(result, {"user":"a user","pass":"a password","verify":"a password","passMatch":true})
|
|
||||||
t.equal(output, 'Username: (test-user) Password: (<default hidden>) Password again: (<default hidden>) ')
|
|
||||||
t.end()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
function child () {
|
|
||||||
read({prompt: "Username: ", default: "test-user" }, function (er, user) {
|
|
||||||
read({prompt: "Password: ", default: "test-pass", silent: true }, function (er, pass) {
|
|
||||||
read({prompt: "Password again: ", default: "test-pass", silent: true }, function (er, pass2) {
|
|
||||||
console.error(JSON.stringify({user: user,
|
|
||||||
pass: pass,
|
|
||||||
verify: pass2,
|
|
||||||
passMatch: (pass === pass2)}))
|
|
||||||
if (process.stdin.unref)
|
|
||||||
process.stdin.unref()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
@ -1,60 +0,0 @@
|
|||||||
var tap = require('tap')
|
|
||||||
var read = require('../lib/read.js')
|
|
||||||
|
|
||||||
if (process.argv[2] === 'child') {
|
|
||||||
return child()
|
|
||||||
}
|
|
||||||
|
|
||||||
var CLOSE = 'close'
|
|
||||||
if (process.version.match(/^v0\.6/)) {
|
|
||||||
CLOSE = 'exit'
|
|
||||||
}
|
|
||||||
|
|
||||||
var spawn = require('child_process').spawn
|
|
||||||
|
|
||||||
tap.test('defaults', function (t) {
|
|
||||||
var child = spawn(process.execPath, [__filename, 'child'])
|
|
||||||
var output = ''
|
|
||||||
var write = child.stdin.write.bind(child.stdin)
|
|
||||||
child.stdout.on('data', function (c) {
|
|
||||||
console.error('data %s', c)
|
|
||||||
output += c
|
|
||||||
if (output.match(/Username: \(test-user\) $/)) {
|
|
||||||
process.nextTick(write.bind(null, '\n'))
|
|
||||||
} else if (output.match(/Password: \(<default hidden>\) $/)) {
|
|
||||||
process.nextTick(write.bind(null, '\n'))
|
|
||||||
} else if (output.match(/Password again: \(<default hidden>\) $/)) {
|
|
||||||
process.nextTick(write.bind(null, '\n'))
|
|
||||||
} else {
|
|
||||||
console.error('prompts done, output=%j', output)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
var result = ''
|
|
||||||
child.stderr.on('data', function (c) {
|
|
||||||
result += c
|
|
||||||
console.error('result %j', c.toString())
|
|
||||||
})
|
|
||||||
|
|
||||||
child.on(CLOSE, function () {
|
|
||||||
result = JSON.parse(result)
|
|
||||||
t.same(result, {"user":"test-user","pass":"test-pass","verify":"test-pass","passMatch":true})
|
|
||||||
t.equal(output, 'Username: (test-user) Password: (<default hidden>) Password again: (<default hidden>) ')
|
|
||||||
t.end()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
function child () {
|
|
||||||
read({prompt: "Username: ", default: "test-user" }, function (er, user) {
|
|
||||||
read({prompt: "Password: ", default: "test-pass", silent: true }, function (er, pass) {
|
|
||||||
read({prompt: "Password again: ", default: "test-pass", silent: true }, function (er, pass2) {
|
|
||||||
console.error(JSON.stringify({user: user,
|
|
||||||
pass: pass,
|
|
||||||
verify: pass2,
|
|
||||||
passMatch: (pass === pass2)}))
|
|
||||||
if (process.stdin.unref)
|
|
||||||
process.stdin.unref()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
@ -1,83 +0,0 @@
|
|||||||
var tap = require('tap')
|
|
||||||
var read = require('../lib/read.js')
|
|
||||||
|
|
||||||
var CLOSE = 'close'
|
|
||||||
if (process.version.match(/^v0\.6/)) {
|
|
||||||
CLOSE = 'exit'
|
|
||||||
}
|
|
||||||
|
|
||||||
if (process.argv[2] === 'child') {
|
|
||||||
return child()
|
|
||||||
}
|
|
||||||
|
|
||||||
var spawn = require('child_process').spawn
|
|
||||||
function child () {
|
|
||||||
read({prompt:'1'}, function (er, r1) {if (er) throw er
|
|
||||||
read({prompt:'2'}, function (er, r2) {if (er) throw er
|
|
||||||
read({prompt:'3'}, function (er, r3) {if (er) throw er
|
|
||||||
read({prompt:'4'}, function (er, r4) {if (er) throw er
|
|
||||||
read({prompt:'5'}, function (er, r5) {if (er) throw er
|
|
||||||
read({prompt:'6'}, function (er, r6) {if (er) throw er
|
|
||||||
read({prompt:'7'}, function (er, r7) {if (er) throw er
|
|
||||||
read({prompt:'8'}, function (er, r8) {if (er) throw er
|
|
||||||
read({prompt:'9'}, function (er, r9) {if (er) throw er
|
|
||||||
read({prompt:'10'}, function (er, r10) {if (er) throw er
|
|
||||||
read({prompt:'11'}, function (er, r11) {if (er) throw er
|
|
||||||
read({prompt:'12'}, function (er, r12) {if (er) throw er
|
|
||||||
read({prompt:'13'}, function (er, r13) {if (er) throw er
|
|
||||||
read({prompt:'14'}, function (er, r14) {if (er) throw er
|
|
||||||
read({prompt:'15'}, function (er, r15) {if (er) throw er
|
|
||||||
read({prompt:'16'}, function (er, r16) {if (er) throw er
|
|
||||||
read({prompt:'17'}, function (er, r17) {if (er) throw er
|
|
||||||
read({prompt:'18'}, function (er, r18) {if (er) throw er
|
|
||||||
console.log(r1, r2, r3, r4, r5, r6, r7, r8, r9, r10,
|
|
||||||
r11, r12, r13, r14, r15, r16, r17, r18)
|
|
||||||
if (process.stdin.unref)
|
|
||||||
process.stdin.unref()
|
|
||||||
})})})})})})})})})})})})})})})})})})
|
|
||||||
}
|
|
||||||
|
|
||||||
tap.test('many reads', function (t) {
|
|
||||||
var child = spawn(process.execPath, [__filename, 'child'])
|
|
||||||
var n = 0
|
|
||||||
var output = ''
|
|
||||||
var expect = '1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ' +
|
|
||||||
'16 17 18 1 2 3 4 5 6 7 8 9 10 11 12 ' +
|
|
||||||
'13 14 15 16 17 18\n'
|
|
||||||
var write = child.stdin.write.bind(child.stdin)
|
|
||||||
var answers =
|
|
||||||
[ '1\n',
|
|
||||||
'2\n',
|
|
||||||
'3\n',
|
|
||||||
'4\n',
|
|
||||||
'5\n',
|
|
||||||
'6\n',
|
|
||||||
'7\n',
|
|
||||||
'8\n',
|
|
||||||
'9\n',
|
|
||||||
'10\n',
|
|
||||||
'11\n',
|
|
||||||
'12\n',
|
|
||||||
'13\n',
|
|
||||||
'14\n',
|
|
||||||
'15\n',
|
|
||||||
'16\n',
|
|
||||||
'17\n',
|
|
||||||
'18\n' ]
|
|
||||||
child.stdout.on('data', function (c) {
|
|
||||||
n++;
|
|
||||||
output += c
|
|
||||||
if (answers.length) {
|
|
||||||
write(answers.shift())
|
|
||||||
}
|
|
||||||
})
|
|
||||||
child.stderr.on('data', function (c) {
|
|
||||||
output += c
|
|
||||||
console.error('' + c)
|
|
||||||
})
|
|
||||||
child.on(CLOSE, function (c) {
|
|
||||||
t.equal(output, expect)
|
|
||||||
t.equal(n, 19)
|
|
||||||
t.end()
|
|
||||||
})
|
|
||||||
})
|
|
@ -1,2 +0,0 @@
|
|||||||
node_modules
|
|
||||||
npm-debug.log
|
|
@ -1,11 +0,0 @@
|
|||||||
language: node_js
|
|
||||||
node_js:
|
|
||||||
- "0.8"
|
|
||||||
- "0.10"
|
|
||||||
- "0.11"
|
|
||||||
|
|
||||||
notifications:
|
|
||||||
email:
|
|
||||||
- travis@nodejitsu.com
|
|
||||||
irc: "irc.freenode.org#nodejitsu"
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
|||||||
|
|
||||||
0.1.3 / 2012-10-17
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Fixed case problem with types
|
|
||||||
|
|
||||||
0.1.2 / 2012-06-27
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Added host-name String format
|
|
||||||
* Added support for additionalProperties
|
|
||||||
* Added few default validation messages for formats
|
|
||||||
|
|
||||||
0.1.1 / 2012-04-16
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Added default and custom error message support
|
|
||||||
* Added suport for conform function
|
|
||||||
* Updated date-time format
|
|
||||||
|
|
||||||
0.1.0 / 2011-11-09
|
|
||||||
=================
|
|
||||||
|
|
||||||
* Initial release
|
|
||||||
|
|
@ -1,179 +0,0 @@
|
|||||||
|
|
||||||
Apache License
|
|
||||||
Version 2.0, January 2004
|
|
||||||
http://www.apache.org/licenses/
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
||||||
|
|
||||||
1. Definitions.
|
|
||||||
|
|
||||||
"License" shall mean the terms and conditions for use, reproduction,
|
|
||||||
and distribution as defined by Sections 1 through 9 of this document.
|
|
||||||
|
|
||||||
"Licensor" shall mean the copyright owner or entity authorized by
|
|
||||||
the copyright owner that is granting the License.
|
|
||||||
|
|
||||||
"Legal Entity" shall mean the union of the acting entity and all
|
|
||||||
other entities that control, are controlled by, or are under common
|
|
||||||
control with that entity. For the purposes of this definition,
|
|
||||||
"control" means (i) the power, direct or indirect, to cause the
|
|
||||||
direction or management of such entity, whether by contract or
|
|
||||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
||||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
||||||
|
|
||||||
"You" (or "Your") shall mean an individual or Legal Entity
|
|
||||||
exercising permissions granted by this License.
|
|
||||||
|
|
||||||
"Source" form shall mean the preferred form for making modifications,
|
|
||||||
including but not limited to software source code, documentation
|
|
||||||
source, and configuration files.
|
|
||||||
|
|
||||||
"Object" form shall mean any form resulting from mechanical
|
|
||||||
transformation or translation of a Source form, including but
|
|
||||||
not limited to compiled object code, generated documentation,
|
|
||||||
and conversions to other media types.
|
|
||||||
|
|
||||||
"Work" shall mean the work of authorship, whether in Source or
|
|
||||||
Object form, made available under the License, as indicated by a
|
|
||||||
copyright notice that is included in or attached to the work
|
|
||||||
(an example is provided in the Appendix below).
|
|
||||||
|
|
||||||
"Derivative Works" shall mean any work, whether in Source or Object
|
|
||||||
form, that is based on (or derived from) the Work and for which the
|
|
||||||
editorial revisions, annotations, elaborations, or other modifications
|
|
||||||
represent, as a whole, an original work of authorship. For the purposes
|
|
||||||
of this License, Derivative Works shall not include works that remain
|
|
||||||
separable from, or merely link (or bind by name) to the interfaces of,
|
|
||||||
the Work and Derivative Works thereof.
|
|
||||||
|
|
||||||
"Contribution" shall mean any work of authorship, including
|
|
||||||
the original version of the Work and any modifications or additions
|
|
||||||
to that Work or Derivative Works thereof, that is intentionally
|
|
||||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
||||||
or by an individual or Legal Entity authorized to submit on behalf of
|
|
||||||
the copyright owner. For the purposes of this definition, "submitted"
|
|
||||||
means any form of electronic, verbal, or written communication sent
|
|
||||||
to the Licensor or its representatives, including but not limited to
|
|
||||||
communication on electronic mailing lists, source code control systems,
|
|
||||||
and issue tracking systems that are managed by, or on behalf of, the
|
|
||||||
Licensor for the purpose of discussing and improving the Work, but
|
|
||||||
excluding communication that is conspicuously marked or otherwise
|
|
||||||
designated in writing by the copyright owner as "Not a Contribution."
|
|
||||||
|
|
||||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
||||||
on behalf of whom a Contribution has been received by Licensor and
|
|
||||||
subsequently incorporated within the Work.
|
|
||||||
|
|
||||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
copyright license to reproduce, prepare Derivative Works of,
|
|
||||||
publicly display, publicly perform, sublicense, and distribute the
|
|
||||||
Work and such Derivative Works in Source or Object form.
|
|
||||||
|
|
||||||
3. Grant of Patent License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
(except as stated in this section) patent license to make, have made,
|
|
||||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
||||||
where such license applies only to those patent claims licensable
|
|
||||||
by such Contributor that are necessarily infringed by their
|
|
||||||
Contribution(s) alone or by combination of their Contribution(s)
|
|
||||||
with the Work to which such Contribution(s) was submitted. If You
|
|
||||||
institute patent litigation against any entity (including a
|
|
||||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
||||||
or a Contribution incorporated within the Work constitutes direct
|
|
||||||
or contributory patent infringement, then any patent licenses
|
|
||||||
granted to You under this License for that Work shall terminate
|
|
||||||
as of the date such litigation is filed.
|
|
||||||
|
|
||||||
4. Redistribution. You may reproduce and distribute copies of the
|
|
||||||
Work or Derivative Works thereof in any medium, with or without
|
|
||||||
modifications, and in Source or Object form, provided that You
|
|
||||||
meet the following conditions:
|
|
||||||
|
|
||||||
(a) You must give any other recipients of the Work or
|
|
||||||
Derivative Works a copy of this License; and
|
|
||||||
|
|
||||||
(b) You must cause any modified files to carry prominent notices
|
|
||||||
stating that You changed the files; and
|
|
||||||
|
|
||||||
(c) You must retain, in the Source form of any Derivative Works
|
|
||||||
that You distribute, all copyright, patent, trademark, and
|
|
||||||
attribution notices from the Source form of the Work,
|
|
||||||
excluding those notices that do not pertain to any part of
|
|
||||||
the Derivative Works; and
|
|
||||||
|
|
||||||
(d) If the Work includes a "NOTICE" text file as part of its
|
|
||||||
distribution, then any Derivative Works that You distribute must
|
|
||||||
include a readable copy of the attribution notices contained
|
|
||||||
within such NOTICE file, excluding those notices that do not
|
|
||||||
pertain to any part of the Derivative Works, in at least one
|
|
||||||
of the following places: within a NOTICE text file distributed
|
|
||||||
as part of the Derivative Works; within the Source form or
|
|
||||||
documentation, if provided along with the Derivative Works; or,
|
|
||||||
within a display generated by the Derivative Works, if and
|
|
||||||
wherever such third-party notices normally appear. The contents
|
|
||||||
of the NOTICE file are for informational purposes only and
|
|
||||||
do not modify the License. You may add Your own attribution
|
|
||||||
notices within Derivative Works that You distribute, alongside
|
|
||||||
or as an addendum to the NOTICE text from the Work, provided
|
|
||||||
that such additional attribution notices cannot be construed
|
|
||||||
as modifying the License.
|
|
||||||
|
|
||||||
You may add Your own copyright statement to Your modifications and
|
|
||||||
may provide additional or different license terms and conditions
|
|
||||||
for use, reproduction, or distribution of Your modifications, or
|
|
||||||
for any such Derivative Works as a whole, provided Your use,
|
|
||||||
reproduction, and distribution of the Work otherwise complies with
|
|
||||||
the conditions stated in this License.
|
|
||||||
|
|
||||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
||||||
any Contribution intentionally submitted for inclusion in the Work
|
|
||||||
by You to the Licensor shall be under the terms and conditions of
|
|
||||||
this License, without any additional terms or conditions.
|
|
||||||
Notwithstanding the above, nothing herein shall supersede or modify
|
|
||||||
the terms of any separate license agreement you may have executed
|
|
||||||
with Licensor regarding such Contributions.
|
|
||||||
|
|
||||||
6. Trademarks. This License does not grant permission to use the trade
|
|
||||||
names, trademarks, service marks, or product names of the Licensor,
|
|
||||||
except as required for reasonable and customary use in describing the
|
|
||||||
origin of the Work and reproducing the content of the NOTICE file.
|
|
||||||
|
|
||||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
||||||
agreed to in writing, Licensor provides the Work (and each
|
|
||||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
implied, including, without limitation, any warranties or conditions
|
|
||||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
||||||
appropriateness of using or redistributing the Work and assume any
|
|
||||||
risks associated with Your exercise of permissions under this License.
|
|
||||||
|
|
||||||
8. Limitation of Liability. In no event and under no legal theory,
|
|
||||||
whether in tort (including negligence), contract, or otherwise,
|
|
||||||
unless required by applicable law (such as deliberate and grossly
|
|
||||||
negligent acts) or agreed to in writing, shall any Contributor be
|
|
||||||
liable to You for damages, including any direct, indirect, special,
|
|
||||||
incidental, or consequential damages of any character arising as a
|
|
||||||
result of this License or out of the use or inability to use the
|
|
||||||
Work (including but not limited to damages for loss of goodwill,
|
|
||||||
work stoppage, computer failure or malfunction, or any and all
|
|
||||||
other commercial damages or losses), even if such Contributor
|
|
||||||
has been advised of the possibility of such damages.
|
|
||||||
|
|
||||||
9. Accepting Warranty or Additional Liability. While redistributing
|
|
||||||
the Work or Derivative Works thereof, You may choose to offer,
|
|
||||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
||||||
or other liability obligations and/or rights consistent with this
|
|
||||||
License. However, in accepting such obligations, You may act only
|
|
||||||
on Your own behalf and on Your sole responsibility, not on behalf
|
|
||||||
of any other Contributor, and only if You agree to indemnify,
|
|
||||||
defend, and hold each Contributor harmless for any liability
|
|
||||||
incurred by, or claims asserted against, such Contributor by reason
|
|
||||||
of your accepting any such warranty or additional liability.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
Copyright (c) 2009-2010 Alexis Sellier, Charlie Robbins, Nodejitsu Inc.
|
|
@ -1,301 +0,0 @@
|
|||||||
# revalidator [](http://travis-ci.org/flatiron/revalidator)
|
|
||||||
|
|
||||||
A cross-browser / node.js validator used by resourceful and flatiron. Revalidator has [JSONSchema](http://tools.ietf.org/html/draft-zyp-json-schema-04) compatibility as primary goal.
|
|
||||||
|
|
||||||
## Example
|
|
||||||
The core of `revalidator` is simple and succinct: `revalidator.validate(obj, schema)`:
|
|
||||||
|
|
||||||
``` js
|
|
||||||
var revalidator = require('revalidator');
|
|
||||||
|
|
||||||
console.dir(revalidator.validate(someObject, {
|
|
||||||
properties: {
|
|
||||||
url: {
|
|
||||||
description: 'the url the object should be stored at',
|
|
||||||
type: 'string',
|
|
||||||
pattern: '^/[^#%&*{}\\:<>?\/+]+$',
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
challenge: {
|
|
||||||
description: 'a means of protecting data (insufficient for production, used as example)',
|
|
||||||
type: 'string',
|
|
||||||
minLength: 5
|
|
||||||
},
|
|
||||||
body: {
|
|
||||||
description: 'what to store at the url',
|
|
||||||
type: 'any',
|
|
||||||
default: null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
```
|
|
||||||
|
|
||||||
This will return with a value indicating if the `obj` conforms to the `schema`. If it does not, a descriptive object will be returned containing the errors encountered with validation.
|
|
||||||
|
|
||||||
``` js
|
|
||||||
{
|
|
||||||
valid: true // or false
|
|
||||||
errors: [/* Array of errors if valid is false */]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
In the browser, the validation function is exposed on `window.validate` by simply including `revalidator.js`.
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
### Installing npm (node package manager)
|
|
||||||
``` bash
|
|
||||||
$ curl http://npmjs.org/install.sh | sh
|
|
||||||
```
|
|
||||||
|
|
||||||
### Installing revalidator
|
|
||||||
``` bash
|
|
||||||
$ [sudo] npm install revalidator
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
`revalidator` takes json-schema as input to validate objects.
|
|
||||||
|
|
||||||
### revalidator.validate (obj, schema, options)
|
|
||||||
|
|
||||||
This will return with a value indicating if the `obj` conforms to the `schema`. If it does not, a descriptive object will be returned containing the errors encountered with validation.
|
|
||||||
|
|
||||||
``` js
|
|
||||||
{
|
|
||||||
valid: true // or false
|
|
||||||
errors: [/* Array of errors if valid is false */]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Available Options
|
|
||||||
|
|
||||||
* __validateFormats__: Enforce format constraints (_default true_)
|
|
||||||
* __validateFormatsStrict__: When `validateFormats` is _true_ treat unrecognized formats as validation errors (_default false_)
|
|
||||||
* __validateFormatExtensions__: When `validateFormats` is _true_ also validate formats defined in `validate.formatExtensions` (_default true_)
|
|
||||||
* __cast__: Enforce casting of some types (for integers/numbers are only supported) when it's possible, e.g. `"42" => 42`, but `"forty2" => "forty2"` for the `integer` type.
|
|
||||||
|
|
||||||
### Schema
|
|
||||||
For a property an `value` is that which is given as input for validation where as an `expected value` is the value of the below fields
|
|
||||||
|
|
||||||
#### required
|
|
||||||
If true, the value should not be undefined
|
|
||||||
|
|
||||||
```js
|
|
||||||
{ required: true }
|
|
||||||
```
|
|
||||||
|
|
||||||
#### allowEmpty
|
|
||||||
If false, the value must not be an empty string
|
|
||||||
|
|
||||||
```js
|
|
||||||
{ allowEmpty: false }
|
|
||||||
```
|
|
||||||
|
|
||||||
#### type
|
|
||||||
The `type of value` should be equal to the expected value
|
|
||||||
|
|
||||||
```js
|
|
||||||
{ type: 'string' }
|
|
||||||
{ type: 'number' }
|
|
||||||
{ type: 'integer' }
|
|
||||||
{ type: 'array' }
|
|
||||||
{ type: 'boolean' }
|
|
||||||
{ type: 'object' }
|
|
||||||
{ type: 'null' }
|
|
||||||
{ type: 'any' }
|
|
||||||
{ type: ['boolean', 'string'] }
|
|
||||||
```
|
|
||||||
|
|
||||||
#### pattern
|
|
||||||
The expected value regex needs to be satisfied by the value
|
|
||||||
|
|
||||||
```js
|
|
||||||
{ pattern: /^[a-z]+$/ }
|
|
||||||
```
|
|
||||||
|
|
||||||
#### maxLength
|
|
||||||
The length of value must be greater than or equal to expected value
|
|
||||||
|
|
||||||
```js
|
|
||||||
{ maxLength: 8 }
|
|
||||||
```
|
|
||||||
|
|
||||||
#### minLength
|
|
||||||
The length of value must be lesser than or equal to expected value
|
|
||||||
|
|
||||||
```js
|
|
||||||
{ minLength: 8 }
|
|
||||||
```
|
|
||||||
|
|
||||||
#### minimum
|
|
||||||
Value must be greater than or equal to the expected value
|
|
||||||
|
|
||||||
```js
|
|
||||||
{ minimum: 10 }
|
|
||||||
```
|
|
||||||
|
|
||||||
#### maximum
|
|
||||||
Value must be lesser than or equal to the expected value
|
|
||||||
|
|
||||||
```js
|
|
||||||
{ maximum: 10 }
|
|
||||||
```
|
|
||||||
|
|
||||||
#### allowEmpty
|
|
||||||
Value may not be empty
|
|
||||||
|
|
||||||
```js
|
|
||||||
{ allowEmpty: false }
|
|
||||||
```
|
|
||||||
|
|
||||||
#### exclusiveMinimum
|
|
||||||
Value must be greater than expected value
|
|
||||||
|
|
||||||
```js
|
|
||||||
{ exclusiveMinimum: 9 }
|
|
||||||
```
|
|
||||||
|
|
||||||
### exclusiveMaximum
|
|
||||||
Value must be lesser than expected value
|
|
||||||
|
|
||||||
```js
|
|
||||||
{ exclusiveMaximum: 11 }
|
|
||||||
```
|
|
||||||
|
|
||||||
#### divisibleBy
|
|
||||||
Value must be divisible by expected value
|
|
||||||
|
|
||||||
```js
|
|
||||||
{ divisibleBy: 5 }
|
|
||||||
{ divisibleBy: 0.5 }
|
|
||||||
```
|
|
||||||
|
|
||||||
#### minItems
|
|
||||||
Value must contain more then expected value number of items
|
|
||||||
|
|
||||||
```js
|
|
||||||
{ minItems: 2 }
|
|
||||||
```
|
|
||||||
|
|
||||||
#### maxItems
|
|
||||||
Value must contains less then expected value number of items
|
|
||||||
|
|
||||||
```js
|
|
||||||
{ maxItems: 5 }
|
|
||||||
```
|
|
||||||
|
|
||||||
#### uniqueItems
|
|
||||||
Value must hold a unique set of values
|
|
||||||
|
|
||||||
```js
|
|
||||||
{ uniqueItems: true }
|
|
||||||
```
|
|
||||||
|
|
||||||
#### enum
|
|
||||||
Value must be present in the array of expected value
|
|
||||||
|
|
||||||
```js
|
|
||||||
{ enum: ['month', 'year'] }
|
|
||||||
```
|
|
||||||
|
|
||||||
#### format
|
|
||||||
Value must be a valid format
|
|
||||||
|
|
||||||
```js
|
|
||||||
{ format: 'url' }
|
|
||||||
{ format: 'email' }
|
|
||||||
{ format: 'ip-address' }
|
|
||||||
{ format: 'ipv6' }
|
|
||||||
{ format: 'date-time' }
|
|
||||||
{ format: 'date' }
|
|
||||||
{ format: 'time' }
|
|
||||||
{ format: 'color' }
|
|
||||||
{ format: 'host-name' }
|
|
||||||
{ format: 'utc-millisec' }
|
|
||||||
{ format: 'regex' }
|
|
||||||
```
|
|
||||||
|
|
||||||
#### conform
|
|
||||||
Value must conform to constraint denoted by expected value
|
|
||||||
|
|
||||||
```js
|
|
||||||
{ conform: function (v) {
|
|
||||||
if (v%3==1) return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### dependencies
|
|
||||||
Value is valid only if the dependent value is valid
|
|
||||||
|
|
||||||
```js
|
|
||||||
{
|
|
||||||
town: { required: true, dependencies: 'country' },
|
|
||||||
country: { maxLength: 3, required: true }
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Nested Schema
|
|
||||||
We also allow nested schema
|
|
||||||
|
|
||||||
```js
|
|
||||||
{
|
|
||||||
properties: {
|
|
||||||
title: {
|
|
||||||
type: 'string',
|
|
||||||
maxLength: 140,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
author: {
|
|
||||||
type: 'object',
|
|
||||||
required: true,
|
|
||||||
properties: {
|
|
||||||
name: {
|
|
||||||
type: 'string',
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
email: {
|
|
||||||
type: 'string',
|
|
||||||
format: 'email'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Custom Messages
|
|
||||||
We also allow custom message for different constraints
|
|
||||||
|
|
||||||
```js
|
|
||||||
{
|
|
||||||
type: 'string',
|
|
||||||
format: 'url'
|
|
||||||
messages: {
|
|
||||||
type: 'Not a string type',
|
|
||||||
format: 'Expected format is a url'
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```js
|
|
||||||
{
|
|
||||||
conform: function () { ... },
|
|
||||||
message: 'This can be used as a global message'
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Tests
|
|
||||||
All tests are written with [vows][0] and should be run with [npm][1]:
|
|
||||||
|
|
||||||
``` bash
|
|
||||||
$ npm test
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Author: [Charlie Robbins](http://nodejitsu.com), [Alexis Sellier](http://cloudhead.io)
|
|
||||||
#### Contributors: [Fedor Indutny](http://github.com/indutny), [Bradley Meck](http://github.com/bmeck), [Laurie Harper](http://laurie.holoweb.net/)
|
|
||||||
#### License: Apache 2.0
|
|
||||||
|
|
||||||
[0]: http://vowsjs.org
|
|
||||||
[1]: http://npmjs.org
|
|
@ -1,204 +0,0 @@
|
|||||||
//
|
|
||||||
// (C) 2011, Nodejitsu Inc.
|
|
||||||
// MIT License
|
|
||||||
//
|
|
||||||
// A simple web service for storing JSON data via REST
|
|
||||||
//
|
|
||||||
// GET - View Object
|
|
||||||
// POST - Create Object
|
|
||||||
// PUT - Update Object
|
|
||||||
// DELETE - Delete Object
|
|
||||||
//
|
|
||||||
|
|
||||||
var revalidator = require('../'),
|
|
||||||
http = require('http'),
|
|
||||||
//
|
|
||||||
// Keep our objects in a simple memory store
|
|
||||||
//
|
|
||||||
memoryStore = {},
|
|
||||||
//
|
|
||||||
// Set up our request schema
|
|
||||||
//
|
|
||||||
schema = {
|
|
||||||
properties: {
|
|
||||||
url: {
|
|
||||||
description: 'the url the object should be stored at',
|
|
||||||
type: 'string',
|
|
||||||
pattern: '^/[^#%&*{}\\:<>?\/+]+$',
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
challenge: {
|
|
||||||
description: 'a means of protecting data (insufficient for production, used as example)',
|
|
||||||
type: 'string',
|
|
||||||
minLength: 5
|
|
||||||
},
|
|
||||||
body: {
|
|
||||||
description: 'what to store at the url',
|
|
||||||
type: 'any',
|
|
||||||
default: null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var server = http.createServer(function validateRestRequest (req, res) {
|
|
||||||
req.method = req.method.toUpperCase();
|
|
||||||
|
|
||||||
//
|
|
||||||
// Log the requests
|
|
||||||
//
|
|
||||||
console.log(req.method, req.url);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Buffer the request so it can be parsed as JSON
|
|
||||||
//
|
|
||||||
var requestBody = [];
|
|
||||||
req.on('data', function addDataToBody (data) {
|
|
||||||
requestBody.push(data);
|
|
||||||
});
|
|
||||||
|
|
||||||
//
|
|
||||||
// Once the request has ended work with the body
|
|
||||||
//
|
|
||||||
req.on('end', function dealWithRest () {
|
|
||||||
|
|
||||||
//
|
|
||||||
// Parse the JSON
|
|
||||||
//
|
|
||||||
requestBody = requestBody.join('');
|
|
||||||
if ({POST: 1, PUT: 1}[req.method]) {
|
|
||||||
try {
|
|
||||||
requestBody = JSON.parse(requestBody);
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
res.writeHead(400);
|
|
||||||
res.end(e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
requestBody = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// If this was sent to a url but the body url was not declared
|
|
||||||
// Make sure the body get the requested url so that our schema
|
|
||||||
// validates before we work on it
|
|
||||||
//
|
|
||||||
if (!requestBody.url) {
|
|
||||||
requestBody.url = req.url;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Don't let users override the main API endpoint
|
|
||||||
//
|
|
||||||
if (requestBody.url === '/') {
|
|
||||||
res.writeHead(400);
|
|
||||||
res.end('Cannot override the API endpoint "/"');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// See if our request and target are out of sync
|
|
||||||
// This lets us double check the url we are about to take up
|
|
||||||
// if we choose to send the request to the url directly
|
|
||||||
//
|
|
||||||
if (req.url !== '/' && requestBody.url !== req.url) {
|
|
||||||
res.writeHead(400);
|
|
||||||
res.end('Requested url and actual url do not match');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Validate the schema
|
|
||||||
//
|
|
||||||
var validation = revalidator.validate(requestBody, schema);
|
|
||||||
if (!validation.valid) {
|
|
||||||
res.writeHead(400);
|
|
||||||
res.end(validation.errors.join('\n'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Grab the current value from storage and
|
|
||||||
// check if it is a valid state for REST
|
|
||||||
//
|
|
||||||
var storedValue = memoryStore[requestBody.url];
|
|
||||||
if (req.method === 'POST') {
|
|
||||||
if (storedValue) {
|
|
||||||
res.writeHead(400);
|
|
||||||
res.end('ALREADY EXISTS');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (!storedValue) {
|
|
||||||
res.writeHead(404);
|
|
||||||
res.end('DOES NOT EXIST');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Check our challenge
|
|
||||||
//
|
|
||||||
if (storedValue && requestBody.challenge != storedValue.challenge) {
|
|
||||||
res.writeHead(403);
|
|
||||||
res.end('NOT AUTHORIZED');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Since revalidator only checks and does not manipulate
|
|
||||||
// our object we need to set up the defaults our selves
|
|
||||||
// For an easier solution to this please look at Flatiron's
|
|
||||||
// `Resourceful` project
|
|
||||||
//
|
|
||||||
if (requestBody.body === undefined) {
|
|
||||||
requestBody.body = schema.properties.body.default;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Use REST to determine how to manipulate the stored
|
|
||||||
// values
|
|
||||||
//
|
|
||||||
switch (req.method) {
|
|
||||||
|
|
||||||
case "GET":
|
|
||||||
res.writeHead(200);
|
|
||||||
var result = storedValue.body;
|
|
||||||
res.end(JSON.stringify(result));
|
|
||||||
return;
|
|
||||||
|
|
||||||
case "POST":
|
|
||||||
res.writeHead(201);
|
|
||||||
res.end();
|
|
||||||
memoryStore[requestBody.url] = requestBody;
|
|
||||||
return;
|
|
||||||
|
|
||||||
case "DELETE":
|
|
||||||
delete memoryStore[requestBody.url];
|
|
||||||
res.writeHead(200);
|
|
||||||
res.end();
|
|
||||||
return;
|
|
||||||
|
|
||||||
case "PUT":
|
|
||||||
memoryStore[requestBody.url] = requestBody;
|
|
||||||
res.writeHead(200);
|
|
||||||
res.end();
|
|
||||||
return;
|
|
||||||
|
|
||||||
default:
|
|
||||||
res.writeHead(400);
|
|
||||||
res.end('Invalid Http Verb');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
})
|
|
||||||
//
|
|
||||||
// Listen to various ports depending on environment we are being run on
|
|
||||||
//
|
|
||||||
server.listen(process.env.PORT || process.env.C9_PORT || 1337, function reportListening () {
|
|
||||||
|
|
||||||
console.log('JSON REST Service listening on port', this.address().port);
|
|
||||||
console.log('Requests can be sent via REST to "/" if they conform to the following schema:');
|
|
||||||
console.log(JSON.stringify(schema, null, ' '));
|
|
||||||
|
|
||||||
});
|
|
@ -1,427 +0,0 @@
|
|||||||
(function (exports) {
|
|
||||||
exports.validate = validate;
|
|
||||||
exports.mixin = mixin;
|
|
||||||
|
|
||||||
//
|
|
||||||
// ### function validate (object, schema, options)
|
|
||||||
// #### {Object} object the object to validate.
|
|
||||||
// #### {Object} schema (optional) the JSON Schema to validate against.
|
|
||||||
// #### {Object} options (optional) options controlling the validation
|
|
||||||
// process. See {@link #validate.defaults) for details.
|
|
||||||
// Validate <code>object</code> against a JSON Schema.
|
|
||||||
// If <code>object</code> is self-describing (i.e. has a
|
|
||||||
// <code>$schema</code> property), it will also be validated
|
|
||||||
// against the referenced schema. [TODO]: This behaviour bay be
|
|
||||||
// suppressed by setting the {@link #validate.options.???}
|
|
||||||
// option to <code>???</code>.[/TODO]
|
|
||||||
//
|
|
||||||
// If <code>schema</code> is not specified, and <code>object</code>
|
|
||||||
// is not self-describing, validation always passes.
|
|
||||||
//
|
|
||||||
// <strong>Note:</strong> in order to pass options but no schema,
|
|
||||||
// <code>schema</code> <em>must</em> be specified in the call to
|
|
||||||
// <code>validate()</code>; otherwise, <code>options</code> will
|
|
||||||
// be interpreted as the schema. <code>schema</code> may be passed
|
|
||||||
// as <code>null</code>, <code>undefinded</code>, or the empty object
|
|
||||||
// (<code>{}</code>) in this case.
|
|
||||||
//
|
|
||||||
function validate(object, schema, options) {
|
|
||||||
options = mixin({}, options, validate.defaults);
|
|
||||||
var errors = [];
|
|
||||||
|
|
||||||
validateObject(object, schema, options, errors);
|
|
||||||
|
|
||||||
//
|
|
||||||
// TODO: self-described validation
|
|
||||||
// if (! options.selfDescribing) { ... }
|
|
||||||
//
|
|
||||||
|
|
||||||
return {
|
|
||||||
valid: !(errors.length),
|
|
||||||
errors: errors
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default validation options. Defaults can be overridden by
|
|
||||||
* passing an 'options' hash to {@link #validate}. They can
|
|
||||||
* also be set globally be changing the values in
|
|
||||||
* <code>validate.defaults</code> directly.
|
|
||||||
*/
|
|
||||||
validate.defaults = {
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* Enforce 'format' constraints.
|
|
||||||
* </p><p>
|
|
||||||
* <em>Default: <code>true</code></em>
|
|
||||||
* </p>
|
|
||||||
*/
|
|
||||||
validateFormats: true,
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* When {@link #validateFormats} is <code>true</code>,
|
|
||||||
* treat unrecognized formats as validation errors.
|
|
||||||
* </p><p>
|
|
||||||
* <em>Default: <code>false</code></em>
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @see validation.formats for default supported formats.
|
|
||||||
*/
|
|
||||||
validateFormatsStrict: false,
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* When {@link #validateFormats} is <code>true</code>,
|
|
||||||
* also validate formats defined in {@link #validate.formatExtensions}.
|
|
||||||
* </p><p>
|
|
||||||
* <em>Default: <code>true</code></em>
|
|
||||||
* </p>
|
|
||||||
*/
|
|
||||||
validateFormatExtensions: true
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default messages to include with validation errors.
|
|
||||||
*/
|
|
||||||
validate.messages = {
|
|
||||||
required: "is required",
|
|
||||||
allowEmpty: "must not be empty",
|
|
||||||
minLength: "is too short (minimum is %{expected} characters)",
|
|
||||||
maxLength: "is too long (maximum is %{expected} characters)",
|
|
||||||
pattern: "invalid input",
|
|
||||||
minimum: "must be greater than or equal to %{expected}",
|
|
||||||
maximum: "must be less than or equal to %{expected}",
|
|
||||||
exclusiveMinimum: "must be greater than %{expected}",
|
|
||||||
exclusiveMaximum: "must be less than %{expected}",
|
|
||||||
divisibleBy: "must be divisible by %{expected}",
|
|
||||||
minItems: "must contain more than %{expected} items",
|
|
||||||
maxItems: "must contain less than %{expected} items",
|
|
||||||
uniqueItems: "must hold a unique set of values",
|
|
||||||
format: "is not a valid %{expected}",
|
|
||||||
conform: "must conform to given constraint",
|
|
||||||
type: "must be of %{expected} type"
|
|
||||||
};
|
|
||||||
validate.messages['enum'] = "must be present in given enumerator";
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
validate.formats = {
|
|
||||||
'email': /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i,
|
|
||||||
'ip-address': /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/i,
|
|
||||||
'ipv6': /^([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4}$/,
|
|
||||||
'date-time': /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:.\d{1,3})?Z$/,
|
|
||||||
'date': /^\d{4}-\d{2}-\d{2}$/,
|
|
||||||
'time': /^\d{2}:\d{2}:\d{2}$/,
|
|
||||||
'color': /^#[a-z0-9]{6}|#[a-z0-9]{3}|(?:rgb\(\s*(?:[+-]?\d+%?)\s*,\s*(?:[+-]?\d+%?)\s*,\s*(?:[+-]?\d+%?)\s*\))aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow$/i,
|
|
||||||
//'style': (not supported)
|
|
||||||
//'phone': (not supported)
|
|
||||||
//'uri': (not supported)
|
|
||||||
'host-name': /^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])/,
|
|
||||||
'utc-millisec': {
|
|
||||||
test: function (value) {
|
|
||||||
return typeof(value) === 'number' && value >= 0;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'regex': {
|
|
||||||
test: function (value) {
|
|
||||||
try { new RegExp(value) }
|
|
||||||
catch (e) { return false }
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
validate.formatExtensions = {
|
|
||||||
'url': /^(https?|ftp|git):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i
|
|
||||||
};
|
|
||||||
|
|
||||||
function mixin(obj) {
|
|
||||||
var sources = Array.prototype.slice.call(arguments, 1);
|
|
||||||
while (sources.length) {
|
|
||||||
var source = sources.shift();
|
|
||||||
if (!source) { continue }
|
|
||||||
|
|
||||||
if (typeof(source) !== 'object') {
|
|
||||||
throw new TypeError('mixin non-object');
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var p in source) {
|
|
||||||
if (source.hasOwnProperty(p)) {
|
|
||||||
obj[p] = source[p];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return obj;
|
|
||||||
};
|
|
||||||
|
|
||||||
function validateObject(object, schema, options, errors) {
|
|
||||||
var props, allProps = Object.keys(object),
|
|
||||||
visitedProps = [];
|
|
||||||
|
|
||||||
// see 5.2
|
|
||||||
if (schema.properties) {
|
|
||||||
props = schema.properties;
|
|
||||||
for (var p in props) {
|
|
||||||
if (props.hasOwnProperty(p)) {
|
|
||||||
visitedProps.push(p);
|
|
||||||
validateProperty(object, object[p], p, props[p], options, errors);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// see 5.3
|
|
||||||
if (schema.patternProperties) {
|
|
||||||
props = schema.patternProperties;
|
|
||||||
for (var p in props) {
|
|
||||||
if (props.hasOwnProperty(p)) {
|
|
||||||
var re = new RegExp(p);
|
|
||||||
|
|
||||||
// Find all object properties that are matching `re`
|
|
||||||
for (var k in object) {
|
|
||||||
if (object.hasOwnProperty(k)) {
|
|
||||||
visitedProps.push(k);
|
|
||||||
if (re.exec(k) !== null) {
|
|
||||||
validateProperty(object, object[k], p, props[p], options, errors);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// see 5.4
|
|
||||||
if (undefined !== schema.additionalProperties) {
|
|
||||||
var i, l;
|
|
||||||
|
|
||||||
var unvisitedProps = allProps.filter(function(k){
|
|
||||||
return -1 === visitedProps.indexOf(k);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Prevent additional properties; each unvisited property is therefore an error
|
|
||||||
if (schema.additionalProperties === false && unvisitedProps.length > 0) {
|
|
||||||
for (i = 0, l = unvisitedProps.length; i < l; i++) {
|
|
||||||
error("additionalProperties", unvisitedProps[i], object[unvisitedProps[i]], false, errors);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// additionalProperties is a schema and validate unvisited properties against that schema
|
|
||||||
else if (typeof schema.additionalProperties == "object" && unvisitedProps.length > 0) {
|
|
||||||
for (i = 0, l = unvisitedProps.length; i < l; i++) {
|
|
||||||
validateProperty(object, object[unvisitedProps[i]], unvisitedProps[i], schema.unvisitedProperties, options, errors);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
function validateProperty(object, value, property, schema, options, errors) {
|
|
||||||
var format,
|
|
||||||
valid,
|
|
||||||
spec,
|
|
||||||
type;
|
|
||||||
|
|
||||||
function constrain(name, value, assert) {
|
|
||||||
if (schema[name] !== undefined && !assert(value, schema[name])) {
|
|
||||||
error(name, property, value, schema, errors);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value === undefined) {
|
|
||||||
if (schema.required && schema.type !== 'any') {
|
|
||||||
return error('required', property, undefined, schema, errors);
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.cast) {
|
|
||||||
if (('integer' === schema.type || 'number' === schema.type) && value == +value) {
|
|
||||||
value = +value;
|
|
||||||
object[property] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ('boolean' === schema.type) {
|
|
||||||
if ('true' === value || '1' === value || 1 === value) {
|
|
||||||
value = true;
|
|
||||||
object[property] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ('false' === value || '0' === value || 0 === value) {
|
|
||||||
value = false;
|
|
||||||
object[property] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (schema.format && options.validateFormats) {
|
|
||||||
format = schema.format;
|
|
||||||
|
|
||||||
if (options.validateFormatExtensions) { spec = validate.formatExtensions[format] }
|
|
||||||
if (!spec) { spec = validate.formats[format] }
|
|
||||||
if (!spec) {
|
|
||||||
if (options.validateFormatsStrict) {
|
|
||||||
return error('format', property, value, schema, errors);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (!spec.test(value)) {
|
|
||||||
return error('format', property, value, schema, errors);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (schema['enum'] && schema['enum'].indexOf(value) === -1) {
|
|
||||||
error('enum', property, value, schema, errors);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dependencies (see 5.8)
|
|
||||||
if (typeof schema.dependencies === 'string' &&
|
|
||||||
object[schema.dependencies] === undefined) {
|
|
||||||
error('dependencies', property, null, schema, errors);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isArray(schema.dependencies)) {
|
|
||||||
for (var i = 0, l = schema.dependencies.length; i < l; i++) {
|
|
||||||
if (object[schema.dependencies[i]] === undefined) {
|
|
||||||
error('dependencies', property, null, schema, errors);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof schema.dependencies === 'object') {
|
|
||||||
validateObject(object, schema.dependencies, options, errors);
|
|
||||||
}
|
|
||||||
|
|
||||||
checkType(value, schema.type, function(err, type) {
|
|
||||||
if (err) return error('type', property, typeof value, schema, errors);
|
|
||||||
|
|
||||||
constrain('conform', value, function (a, e) { return e(a, object) });
|
|
||||||
|
|
||||||
switch (type || (isArray(value) ? 'array' : typeof value)) {
|
|
||||||
case 'string':
|
|
||||||
constrain('allowEmpty', value, function (a, e) { return e ? e : a !== '' });
|
|
||||||
constrain('minLength', value.length, function (a, e) { return a >= e });
|
|
||||||
constrain('maxLength', value.length, function (a, e) { return a <= e });
|
|
||||||
constrain('pattern', value, function (a, e) {
|
|
||||||
e = typeof e === 'string'
|
|
||||||
? e = new RegExp(e)
|
|
||||||
: e;
|
|
||||||
return e.test(a)
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case 'integer':
|
|
||||||
case 'number':
|
|
||||||
constrain('minimum', value, function (a, e) { return a >= e });
|
|
||||||
constrain('maximum', value, function (a, e) { return a <= e });
|
|
||||||
constrain('exclusiveMinimum', value, function (a, e) { return a > e });
|
|
||||||
constrain('exclusiveMaximum', value, function (a, e) { return a < e });
|
|
||||||
constrain('divisibleBy', value, function (a, e) {
|
|
||||||
var multiplier = Math.max((a - Math.floor(a)).toString().length - 2, (e - Math.floor(e)).toString().length - 2);
|
|
||||||
multiplier = multiplier > 0 ? Math.pow(10, multiplier) : 1;
|
|
||||||
return (a * multiplier) % (e * multiplier) === 0
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case 'array':
|
|
||||||
constrain('items', value, function (a, e) {
|
|
||||||
for (var i = 0, l = a.length; i < l; i++) {
|
|
||||||
validateProperty(object, a[i], property, e, options, errors);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
constrain('minItems', value, function (a, e) { return a.length >= e });
|
|
||||||
constrain('maxItems', value, function (a, e) { return a.length <= e });
|
|
||||||
constrain('uniqueItems', value, function (a) {
|
|
||||||
var h = {};
|
|
||||||
|
|
||||||
for (var i = 0, l = a.length; i < l; i++) {
|
|
||||||
var key = JSON.stringify(a[i]);
|
|
||||||
if (h[key]) return false;
|
|
||||||
h[key] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case 'object':
|
|
||||||
// Recursive validation
|
|
||||||
if (schema.properties || schema.patternProperties || schema.additionalProperties) {
|
|
||||||
validateObject(value, schema, options, errors);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
function checkType(val, type, callback) {
|
|
||||||
var result = false,
|
|
||||||
types = isArray(type) ? type : [type];
|
|
||||||
|
|
||||||
// No type - no check
|
|
||||||
if (type === undefined) return callback(null, type);
|
|
||||||
|
|
||||||
// Go through available types
|
|
||||||
// And fine first matching
|
|
||||||
for (var i = 0, l = types.length; i < l; i++) {
|
|
||||||
type = types[i].toLowerCase().trim();
|
|
||||||
if (type === 'string' ? typeof val === 'string' :
|
|
||||||
type === 'array' ? isArray(val) :
|
|
||||||
type === 'object' ? val && typeof val === 'object' &&
|
|
||||||
!isArray(val) :
|
|
||||||
type === 'number' ? typeof val === 'number' :
|
|
||||||
type === 'integer' ? typeof val === 'number' && ~~val === val :
|
|
||||||
type === 'null' ? val === null :
|
|
||||||
type === 'boolean'? typeof val === 'boolean' :
|
|
||||||
type === 'date' ? isDate(val) :
|
|
||||||
type === 'any' ? typeof val !== 'undefined' : false) {
|
|
||||||
return callback(null, type);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
callback(true);
|
|
||||||
};
|
|
||||||
|
|
||||||
function error(attribute, property, actual, schema, errors) {
|
|
||||||
var lookup = { expected: schema[attribute], actual: actual, attribute: attribute, property: property };
|
|
||||||
var message = schema.messages && schema.messages[attribute] || schema.message || validate.messages[attribute] || "no default message";
|
|
||||||
message = message.replace(/%\{([a-z]+)\}/ig, function (_, match) { return lookup[match.toLowerCase()] || ''; });
|
|
||||||
errors.push({
|
|
||||||
attribute: attribute,
|
|
||||||
property: property,
|
|
||||||
expected: schema[attribute],
|
|
||||||
actual: actual,
|
|
||||||
message: message
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
function isArray(value) {
|
|
||||||
var s = typeof value;
|
|
||||||
if (s === 'object') {
|
|
||||||
if (value) {
|
|
||||||
if (typeof value.length === 'number' &&
|
|
||||||
!(value.propertyIsEnumerable('length')) &&
|
|
||||||
typeof value.splice === 'function') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function isDate(value) {
|
|
||||||
var s = typeof value;
|
|
||||||
if (s === 'object') {
|
|
||||||
if (value) {
|
|
||||||
if (typeof value.getTime === 'function') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
})(typeof module === 'object' && module && module.exports ? module.exports : window);
|
|
@ -1,57 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "revalidator",
|
|
||||||
"version": "0.1.8",
|
|
||||||
"description": "A cross-browser / node.js validator used by resourceful",
|
|
||||||
"license": "Apache 2.0",
|
|
||||||
"author": {
|
|
||||||
"name": "Nodejitsu Inc.",
|
|
||||||
"email": "info@nodejitsu.com"
|
|
||||||
},
|
|
||||||
"maintainers": [
|
|
||||||
{
|
|
||||||
"name": "indexzero",
|
|
||||||
"email": "charlie.robbins@gmail.com"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "fedor.indutny",
|
|
||||||
"email": "fedor.indutny@gmail.com"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "julianduque",
|
|
||||||
"email": "julianduquej@gmail.com"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "http://github.com/flatiron/revalidator.git"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"vows": "0.7.0"
|
|
||||||
},
|
|
||||||
"main": "./lib/revalidator",
|
|
||||||
"scripts": {
|
|
||||||
"test": "vows test/*-test.js --spec"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 0.4.0"
|
|
||||||
},
|
|
||||||
"bugs": {
|
|
||||||
"url": "https://github.com/flatiron/revalidator/issues"
|
|
||||||
},
|
|
||||||
"homepage": "https://github.com/flatiron/revalidator",
|
|
||||||
"_id": "revalidator@0.1.8",
|
|
||||||
"_shasum": "fece61bfa0c1b52a206bd6b18198184bdd523a3b",
|
|
||||||
"_from": "revalidator@0.1.x",
|
|
||||||
"_npmVersion": "1.4.10",
|
|
||||||
"_npmUser": {
|
|
||||||
"name": "julianduque",
|
|
||||||
"email": "julianduquej@gmail.com"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"shasum": "fece61bfa0c1b52a206bd6b18198184bdd523a3b",
|
|
||||||
"tarball": "http://registry.npmjs.org/revalidator/-/revalidator-0.1.8.tgz"
|
|
||||||
},
|
|
||||||
"directories": {},
|
|
||||||
"_resolved": "https://registry.npmjs.org/revalidator/-/revalidator-0.1.8.tgz",
|
|
||||||
"readme": "ERROR: No README data found!"
|
|
||||||
}
|
|
@ -1,421 +0,0 @@
|
|||||||
var assert = require('assert'),
|
|
||||||
vows = require('vows'),
|
|
||||||
revalidator = require('../lib/revalidator');
|
|
||||||
|
|
||||||
function clone(object) {
|
|
||||||
return Object.keys(object).reduce(function (obj, k) {
|
|
||||||
obj[k] = object[k];
|
|
||||||
return obj;
|
|
||||||
}, {});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
function assertInvalid(res) {
|
|
||||||
assert.isObject(res);
|
|
||||||
assert.strictEqual(res.valid, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
function assertValid(res) {
|
|
||||||
assert.isObject(res);
|
|
||||||
assert.strictEqual(res.valid, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
function assertHasError(attr, field) {
|
|
||||||
return function (res) {
|
|
||||||
assert.notEqual(res.errors.length, 0);
|
|
||||||
assert.ok(res.errors.some(function (e) {
|
|
||||||
return e.attribute === attr && (field ? e.property === field : true);
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function assertHasErrorMsg(attr, msg) {
|
|
||||||
return function (res) {
|
|
||||||
assert.notEqual(res.errors.length, 0);
|
|
||||||
assert.ok(res.errors.some(function (e) {
|
|
||||||
return e.attribute === attr && e.message === msg;
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function assertValidates(passingValue, failingValue, attributes) {
|
|
||||||
var schema = {
|
|
||||||
name: 'Resource',
|
|
||||||
properties: { field: {} }
|
|
||||||
};
|
|
||||||
|
|
||||||
var failing;
|
|
||||||
|
|
||||||
if (!attributes) {
|
|
||||||
attributes = failingValue;
|
|
||||||
failing = false;
|
|
||||||
} else {
|
|
||||||
failing = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var attr = Object.keys(attributes)[0];
|
|
||||||
revalidator.mixin(schema.properties.field, attributes);
|
|
||||||
|
|
||||||
var result = {
|
|
||||||
"when the object conforms": {
|
|
||||||
topic: function () {
|
|
||||||
return revalidator.validate({ field: passingValue }, schema);
|
|
||||||
},
|
|
||||||
"return an object with `valid` set to true": assertValid
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (failing) {
|
|
||||||
result["when the object does not conform"] ={
|
|
||||||
topic: function () {
|
|
||||||
return revalidator.validate({ field: failingValue }, schema);
|
|
||||||
},
|
|
||||||
"return an object with `valid` set to false": assertInvalid,
|
|
||||||
"and an error concerning the attribute": assertHasError(Object.keys(attributes)[0], 'field')
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
vows.describe('revalidator', {
|
|
||||||
"Validating": {
|
|
||||||
"with <type>:'string'": assertValidates ('hello', 42, { type: "string" }),
|
|
||||||
"with <type>:'number'": assertValidates (42, 'hello', { type: "number" }),
|
|
||||||
"with <type>:'integer'": assertValidates (42, 42.5, { type: "integer" }),
|
|
||||||
"with <type>:'array'": assertValidates ([4, 2], 'hi', { type: "array" }),
|
|
||||||
"with <type>:'object'": assertValidates ({}, [], { type: "object" }),
|
|
||||||
"with <type>:'boolean'": assertValidates (false, 42, { type: "boolean" }),
|
|
||||||
"with <types>:bool,num": assertValidates (false, 'hello', { type: ["boolean", "number"] }),
|
|
||||||
"with <types>:bool,num": assertValidates (544, null, { type: ["boolean", "number"] }),
|
|
||||||
"with <type>:'null'": assertValidates (null, false, { type: "null" }),
|
|
||||||
"with <type>:'any'": assertValidates (9, { type: "any" }),
|
|
||||||
"with <type>:'date'": assertValidates (new Date(), 'hello', { type: "date" }),
|
|
||||||
"with <pattern>": assertValidates ("kaboom", "42", { pattern: /^[a-z]+$/ }),
|
|
||||||
"with <maxLength>": assertValidates ("boom", "kaboom", { maxLength: 4 }),
|
|
||||||
"with <minLength>": assertValidates ("kaboom", "boom", { minLength: 6 }),
|
|
||||||
"with <allowEmpty>": assertValidates ("hello", "", { allowEmpty: false }),
|
|
||||||
"with <minimum>": assertValidates ( 512, 43, { minimum: 473 }),
|
|
||||||
"with <maximum>": assertValidates ( 512, 1949, { maximum: 678 }),
|
|
||||||
"with <divisibleBy>": assertValidates ( 10, 9, { divisibleBy: 5 }),
|
|
||||||
"with <divisibleBy> decimal": assertValidates ( 0.2, 0.009, { divisibleBy: 0.01 }),
|
|
||||||
"with <enum>": assertValidates ("orange", "cigar", { enum: ["orange", "apple", "pear"] }),
|
|
||||||
"with <format>:'url'": assertValidates ('http://test.com/', 'hello', { format: 'url' }),
|
|
||||||
"with <dependencies>": {
|
|
||||||
topic: {
|
|
||||||
properties: {
|
|
||||||
town: { dependencies: "country" },
|
|
||||||
country: { }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"when the object conforms": {
|
|
||||||
topic: function (schema) {
|
|
||||||
return revalidator.validate({ town: "luna", country: "moon" }, schema);
|
|
||||||
},
|
|
||||||
"return an object with `valid` set to true": assertValid
|
|
||||||
},
|
|
||||||
"when the object does not conform": {
|
|
||||||
topic: function (schema) {
|
|
||||||
return revalidator.validate({ town: "luna" }, schema);
|
|
||||||
},
|
|
||||||
"return an object with `valid` set to false": assertInvalid,
|
|
||||||
"and an error concerning the attribute": assertHasError('dependencies')
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"with <dependencies> as array": {
|
|
||||||
topic: {
|
|
||||||
properties: {
|
|
||||||
town: { dependencies: ["country", "planet"] },
|
|
||||||
country: { },
|
|
||||||
planet: { }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"when the object conforms": {
|
|
||||||
topic: function (schema) {
|
|
||||||
return revalidator.validate({ town: "luna", country: "moon", planet: "mars" }, schema);
|
|
||||||
},
|
|
||||||
"return an object with `valid` set to true": assertValid
|
|
||||||
},
|
|
||||||
"when the object does not conform": {
|
|
||||||
topic: function (schema) {
|
|
||||||
return revalidator.validate({ town: "luna", planet: "mars" }, schema);
|
|
||||||
},
|
|
||||||
"return an object with `valid` set to false": assertInvalid,
|
|
||||||
"and an error concerning the attribute": assertHasError('dependencies')
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"with <dependencies> as schema": {
|
|
||||||
topic: {
|
|
||||||
properties: {
|
|
||||||
town: {
|
|
||||||
type: 'string',
|
|
||||||
dependencies: {
|
|
||||||
properties: { x: { type: "number" } }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
country: { }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"when the object conforms": {
|
|
||||||
topic: function (schema) {
|
|
||||||
return revalidator.validate({ town: "luna", x: 1 }, schema);
|
|
||||||
},
|
|
||||||
"return an object with `valid` set to true": assertValid,
|
|
||||||
},
|
|
||||||
"when the object does not conform": {
|
|
||||||
topic: function (schema) {
|
|
||||||
return revalidator.validate({ town: "luna", x: 'no' }, schema);
|
|
||||||
},
|
|
||||||
"return an object with `valid` set to false": assertInvalid
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"with <type>:'integer' and": {
|
|
||||||
"<minimum> constraints": assertValidates ( 512, 43, { minimum: 473, type: 'integer' }),
|
|
||||||
"<maximum> constraints": assertValidates ( 512, 1949, { maximum: 678, type: 'integer' }),
|
|
||||||
"<divisibleBy> constraints": assertValidates ( 10, 9, { divisibleBy: 5, type: 'integer' })
|
|
||||||
},
|
|
||||||
"with <additionalProperties>:false": {
|
|
||||||
topic: {
|
|
||||||
properties: {
|
|
||||||
town: { type: 'string' }
|
|
||||||
},
|
|
||||||
additionalProperties: false
|
|
||||||
},
|
|
||||||
"when the object conforms": {
|
|
||||||
topic: function (schema) {
|
|
||||||
return revalidator.validate({ town: "luna" }, schema);
|
|
||||||
},
|
|
||||||
"return an object with `valid` set to true": assertValid
|
|
||||||
},
|
|
||||||
"when the object does not conform": {
|
|
||||||
topic: function (schema) {
|
|
||||||
return revalidator.validate({ town: "luna", area: 'park' }, schema);
|
|
||||||
},
|
|
||||||
"return an object with `valid` set to false": assertInvalid
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).addBatch({
|
|
||||||
"A schema": {
|
|
||||||
topic: {
|
|
||||||
name: 'Article',
|
|
||||||
properties: {
|
|
||||||
title: {
|
|
||||||
type: 'string',
|
|
||||||
maxLength: 140,
|
|
||||||
conditions: {
|
|
||||||
optional: function () {
|
|
||||||
return !this.published;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
date: { type: 'string', format: 'date', messages: { format: "must be a valid %{expected} and nothing else" } },
|
|
||||||
body: { type: 'string' },
|
|
||||||
tags: {
|
|
||||||
type: 'array',
|
|
||||||
uniqueItems: true,
|
|
||||||
minItems: 2,
|
|
||||||
items: {
|
|
||||||
type: 'string',
|
|
||||||
pattern: /[a-z ]+/
|
|
||||||
}
|
|
||||||
},
|
|
||||||
tuple: {
|
|
||||||
type: 'array',
|
|
||||||
minItems: 2,
|
|
||||||
maxItems: 2,
|
|
||||||
items: {
|
|
||||||
type: ['string', 'number']
|
|
||||||
}
|
|
||||||
},
|
|
||||||
author: { type: 'string', pattern: /^[\w ]+$/i, required: true, messages: { required: "is essential for survival" } },
|
|
||||||
published: { type: 'boolean', 'default': false },
|
|
||||||
category: { type: 'string' },
|
|
||||||
palindrome: {type: 'string', conform: function(val) {
|
|
||||||
return val == val.split("").reverse().join(""); }
|
|
||||||
},
|
|
||||||
name: { type: 'string', default: '', conform: function(val, data) {
|
|
||||||
return (val === data.author); }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
patternProperties: {
|
|
||||||
'^_': {
|
|
||||||
type: 'boolean', default: false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"and an object": {
|
|
||||||
topic: {
|
|
||||||
title: 'Gimme some Gurus',
|
|
||||||
date: '2012-02-04',
|
|
||||||
body: "And I will pwn your codex.",
|
|
||||||
tags: ['energy drinks', 'code'],
|
|
||||||
tuple: ['string0', 103],
|
|
||||||
author: 'cloudhead',
|
|
||||||
published: true,
|
|
||||||
category: 'misc',
|
|
||||||
palindrome: 'dennis sinned',
|
|
||||||
name: 'cloudhead',
|
|
||||||
_flag: true
|
|
||||||
},
|
|
||||||
"can be validated with `revalidator.validate`": {
|
|
||||||
"and if it conforms": {
|
|
||||||
topic: function (object, schema) {
|
|
||||||
return revalidator.validate(object, schema);
|
|
||||||
},
|
|
||||||
"return an object with the `valid` property set to true": assertValid,
|
|
||||||
"return an object with the `errors` property as an empty array": function (res) {
|
|
||||||
assert.isArray(res.errors);
|
|
||||||
assert.isEmpty(res.errors);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"and if it has a missing required property": {
|
|
||||||
topic: function (object, schema) {
|
|
||||||
object = clone(object);
|
|
||||||
delete object.author;
|
|
||||||
return revalidator.validate(object, schema);
|
|
||||||
},
|
|
||||||
"return an object with `valid` set to false": assertInvalid,
|
|
||||||
"and an error concerning the 'required' attribute": assertHasError('required'),
|
|
||||||
"and the error message defined": assertHasErrorMsg('required', "is essential for survival")
|
|
||||||
},
|
|
||||||
"and if it has a missing non-required property": {
|
|
||||||
topic: function (object, schema) {
|
|
||||||
object = clone(object);
|
|
||||||
delete object.category;
|
|
||||||
return revalidator.validate(object, schema);
|
|
||||||
},
|
|
||||||
"return an object with `valid` set to false": assertValid
|
|
||||||
},
|
|
||||||
"and if it has a incorrect pattern property": {
|
|
||||||
topic: function (object, schema) {
|
|
||||||
object = clone(object);
|
|
||||||
object._additionalFlag = 'text';
|
|
||||||
return revalidator.validate(object, schema);
|
|
||||||
},
|
|
||||||
"return an object with `valid` set to false": assertInvalid
|
|
||||||
},
|
|
||||||
"and if it has a incorrect unique array property": {
|
|
||||||
topic: function (object, schema) {
|
|
||||||
object = clone(object);
|
|
||||||
object.tags = ['a', 'a'];
|
|
||||||
return revalidator.validate(object, schema);
|
|
||||||
},
|
|
||||||
"return an object with `valid` set to false": assertInvalid
|
|
||||||
},
|
|
||||||
"and if it has a incorrect array property (wrong values)": {
|
|
||||||
topic: function (object, schema) {
|
|
||||||
object = clone(object);
|
|
||||||
object.tags = ['a', '____'];
|
|
||||||
return revalidator.validate(object, schema);
|
|
||||||
},
|
|
||||||
"return an object with `valid` set to false": assertInvalid
|
|
||||||
},
|
|
||||||
"and if it has a incorrect array property (< minItems)": {
|
|
||||||
topic: function (object, schema) {
|
|
||||||
object = clone(object);
|
|
||||||
object.tags = ['x'];
|
|
||||||
return revalidator.validate(object, schema);
|
|
||||||
},
|
|
||||||
"return an object with `valid` set to false": assertInvalid
|
|
||||||
},
|
|
||||||
"and if it has a incorrect format (date)": {
|
|
||||||
topic: function (object, schema) {
|
|
||||||
object = clone(object);
|
|
||||||
object.date = 'bad date';
|
|
||||||
return revalidator.validate(object, schema);
|
|
||||||
},
|
|
||||||
"return an object with `valid` set to false": assertInvalid,
|
|
||||||
"and the error message defined": assertHasErrorMsg('format', "must be a valid date and nothing else")
|
|
||||||
},
|
|
||||||
"and if it is not a palindrome (conform function)": {
|
|
||||||
topic: function (object, schema) {
|
|
||||||
object = clone(object);
|
|
||||||
object.palindrome = 'bad palindrome';
|
|
||||||
return revalidator.validate(object, schema);
|
|
||||||
},
|
|
||||||
"return an object with `valid` set to false": assertInvalid
|
|
||||||
},
|
|
||||||
"and if it didn't validate a pattern": {
|
|
||||||
topic: function (object, schema) {
|
|
||||||
object = clone(object);
|
|
||||||
object.author = 'email@address.com';
|
|
||||||
return revalidator.validate(object, schema);
|
|
||||||
},
|
|
||||||
"return an object with `valid` set to false": assertInvalid,
|
|
||||||
"and an error concerning the 'pattern' attribute": assertHasError('pattern')
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"with <cast> option": {
|
|
||||||
topic: {
|
|
||||||
properties: {
|
|
||||||
answer: { type: "integer" },
|
|
||||||
is_ready: { type: "boolean" }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"and <integer> property": {
|
|
||||||
"is castable string": {
|
|
||||||
topic: function (schema) {
|
|
||||||
return revalidator.validate({ answer: "42" }, schema, { cast: true });
|
|
||||||
},
|
|
||||||
"return an object with `valid` set to true": assertValid
|
|
||||||
},
|
|
||||||
"is uncastable string": {
|
|
||||||
topic: function (schema) {
|
|
||||||
return revalidator.validate({ answer: "forty2" }, schema, { cast: true });
|
|
||||||
},
|
|
||||||
"return an object with `valid` set to false": assertInvalid
|
|
||||||
},
|
|
||||||
"is casted to integer": {
|
|
||||||
topic: function (schema) {
|
|
||||||
var object = { answer: "42" };
|
|
||||||
revalidator.validate(object, schema, { cast: true });
|
|
||||||
return object;
|
|
||||||
},
|
|
||||||
"return an object with `answer` set to 42": function(res) { assert.strictEqual(res.answer, 42) }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"and <boolean> property": {
|
|
||||||
"is castable 'true/false' string": {
|
|
||||||
topic: function (schema) {
|
|
||||||
return revalidator.validate({ is_ready: "true" }, schema, { cast: true });
|
|
||||||
},
|
|
||||||
"return an object with `valid` set to true": assertValid
|
|
||||||
},
|
|
||||||
"is castable '1/0' string": {
|
|
||||||
topic: function (schema) {
|
|
||||||
return revalidator.validate({ is_ready: "1" }, schema, { cast: true });
|
|
||||||
},
|
|
||||||
"return an object with `valid` set to true": assertValid
|
|
||||||
},
|
|
||||||
"is castable `1/0` integer": {
|
|
||||||
topic: function (schema) {
|
|
||||||
return revalidator.validate({ is_ready: 1 }, schema, { cast: true });
|
|
||||||
},
|
|
||||||
"return an object with `valid` set to true": assertValid
|
|
||||||
},
|
|
||||||
"is uncastable string": {
|
|
||||||
topic: function (schema) {
|
|
||||||
return revalidator.validate({ is_ready: "not yet" }, schema, { cast: true });
|
|
||||||
},
|
|
||||||
"return an object with `valid` set to false": assertInvalid
|
|
||||||
},
|
|
||||||
"is uncastable number": {
|
|
||||||
topic: function (schema) {
|
|
||||||
return revalidator.validate({ is_ready: 42 }, schema, { cast: true });
|
|
||||||
},
|
|
||||||
"return an object with `valid` set to false": assertInvalid
|
|
||||||
},
|
|
||||||
"is casted to boolean": {
|
|
||||||
topic: function (schema) {
|
|
||||||
var object = { is_ready: "true" };
|
|
||||||
revalidator.validate(object, schema, { cast: true });
|
|
||||||
return object;
|
|
||||||
},
|
|
||||||
"return an object with `is_ready` set to true": function(res) { assert.strictEqual(res.is_ready, true) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).export(module);
|
|
@ -1,4 +0,0 @@
|
|||||||
node_modules
|
|
||||||
npm-debug.log
|
|
||||||
*.swp
|
|
||||||
*.swo
|
|
@ -1,10 +0,0 @@
|
|||||||
language: node_js
|
|
||||||
node_js:
|
|
||||||
- 0.6
|
|
||||||
- 0.8
|
|
||||||
|
|
||||||
notifications:
|
|
||||||
email:
|
|
||||||
- travis@nodejitsu.com
|
|
||||||
irc: "irc.freenode.org#nodejitsu"
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
|||||||
|
|
||||||
0.1.5 / 2012-09-18
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Fixed problem with underscore values in camelToUnderscore
|
|
||||||
|
|
||||||
0.1.4 / 2012-07-26
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Made use of inflect for camel to underscore conversion
|
|
||||||
|
|
||||||
0.1.3 / 2012-07-25
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Added camel to underscore conversion and vice-versa
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
|||||||
Copyright (c) 2010 Nodejitsu Inc.
|
|
||||||
|
|
||||||
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.
|
|
@ -1,87 +0,0 @@
|
|||||||
# utile [](http://travis-ci.org/flatiron/utile)
|
|
||||||
|
|
||||||
A drop-in replacement for `util` with some additional advantageous functions
|
|
||||||
|
|
||||||
## Motivation
|
|
||||||
Javascript is definitely a "batteries not included language" when compared to languages like Ruby or Python. Node.js has a simple utility library which exposes some basic (but important) functionality:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ node
|
|
||||||
> var util = require('util');
|
|
||||||
> util.
|
|
||||||
(...)
|
|
||||||
|
|
||||||
util.debug util.error util.exec util.inherits util.inspect
|
|
||||||
util.log util.p util.print util.pump util.puts
|
|
||||||
```
|
|
||||||
|
|
||||||
When one considers their own utility library, why ever bother requiring `util` again? That is the approach taken by this module. To compare:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ node
|
|
||||||
> var utile = require('./lib')
|
|
||||||
> utile.
|
|
||||||
(...)
|
|
||||||
|
|
||||||
utile.async utile.capitalize utile.clone utile.cpr utile.createPath utile.debug
|
|
||||||
utile.each utile.error utile.exec utile.file utile.filter utile.find
|
|
||||||
utile.inherits utile.log utile.mixin utile.mkdirp utile.p utile.path
|
|
||||||
utile.print utile.pump utile.puts utile.randomString utile.requireDir uile.requireDirLazy
|
|
||||||
utile.rimraf
|
|
||||||
```
|
|
||||||
|
|
||||||
As you can see all of the original methods from `util` are there, but there are several new methods specific to `utile`. A note about implementation: _no node.js native modules are modified by utile, it simply copies those methods._
|
|
||||||
|
|
||||||
## Methods
|
|
||||||
The `utile` modules exposes some simple utility methods:
|
|
||||||
|
|
||||||
* `.each(obj, iterator)`: Iterate over the keys of an object.
|
|
||||||
* `.mixin(target [source0, source1, ...])`: Copies enumerable properties from `source0 ... sourceN` onto `target` and returns the resulting object.
|
|
||||||
* `.clone(obj)`: Shallow clones the specified object.
|
|
||||||
* `.capitalize(str)`: Capitalizes the specified `str`.
|
|
||||||
* `.randomString(length)`: randomString returns a pseudo-random ASCII string (subset) the return value is a string of length ⌈bits/6⌉ of characters from the base64 alphabet.
|
|
||||||
* `.filter(obj, test)`: return an object with the properties that `test` returns true on.
|
|
||||||
* `.args(arguments)`: Converts function arguments into actual array with special `callback`, `cb`, `array`, and `last` properties. Also supports *optional* argument contracts. See [the example](https://github.com/flatiron/utile/blob/master/examples/utile-args.js) for more details.
|
|
||||||
* `.requireDir(directory)`: Requires all files and directories from `directory`, returning an object with keys being filenames (without trailing `.js`) and respective values being return values of `require(filename)`.
|
|
||||||
* `.requireDirLazy(directory)`: Lazily requires all files and directories from `directory`, returning an object with keys being filenames (without trailing `.js`) and respective values (getters) being return values of `require(filename)`.
|
|
||||||
* `.format([string] text, [array] formats, [array] replacements)`: Replace `formats` in `text` with `replacements`. This will fall back to the original `util.format` command if it is called improperly.
|
|
||||||
|
|
||||||
## Packaged Dependencies
|
|
||||||
In addition to the methods that are built-in, utile includes a number of commonly used dependencies to reduce the number of includes in your package.json. These modules _are not eagerly loaded to be respectful of startup time,_ but instead are lazy-loaded getters on the `utile` object
|
|
||||||
|
|
||||||
* `.async`: [Async utilities for node and the browser][0]
|
|
||||||
* `.inflect`: [Customizable inflections for node.js][6]
|
|
||||||
* `.mkdirp`: [Recursively mkdir, like mkdir -p, but in node.js][1]
|
|
||||||
* `.rimraf`: [A rm -rf util for nodejs][2]
|
|
||||||
* `.cpr`: [Asynchronous recursive file copying with Node.js][3]
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
### Installing npm (node package manager)
|
|
||||||
```
|
|
||||||
curl http://npmjs.org/install.sh | sh
|
|
||||||
```
|
|
||||||
|
|
||||||
### Installing utile
|
|
||||||
```
|
|
||||||
[sudo] npm install utile
|
|
||||||
```
|
|
||||||
|
|
||||||
## Tests
|
|
||||||
All tests are written with [vows][4] and should be run with [npm][5]:
|
|
||||||
|
|
||||||
``` bash
|
|
||||||
$ npm test
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Author: [Nodejitsu Inc.](http://www.nodejitsu.com)
|
|
||||||
#### Contributors: [Charlie Robbins](http://github.com/indexzero), [Dominic Tarr](http://github.com/dominictarr)
|
|
||||||
#### License: MIT
|
|
||||||
|
|
||||||
[0]: https://github.com/caolan/async
|
|
||||||
[1]: https://github.com/substack/node-mkdirp
|
|
||||||
[2]: https://github.com/isaacs/rimraf
|
|
||||||
[3]: https://github.com/avianflu/ncp
|
|
||||||
[4]: https://vowsjs.org
|
|
||||||
[5]: https://npmjs.org
|
|
||||||
[6]: https://github.com/pksunkara/inflect
|
|
@ -1,46 +0,0 @@
|
|||||||
/*
|
|
||||||
* args.js: function argument parsing helper utility
|
|
||||||
*
|
|
||||||
* (C) 2012, Nodejitsu Inc.
|
|
||||||
* MIT LICENSE
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
var utile = require('./index');
|
|
||||||
|
|
||||||
//
|
|
||||||
// ### function args(_args)
|
|
||||||
// #### _args {Arguments} Original function arguments
|
|
||||||
//
|
|
||||||
// Top-level method will accept a javascript "arguments" object (the actual keyword
|
|
||||||
// "arguments" inside any scope), and attempt to return back an intelligent object
|
|
||||||
// representing the functions arguments
|
|
||||||
//
|
|
||||||
module.exports = function (_args) {
|
|
||||||
var args = utile.rargs(_args),
|
|
||||||
_cb;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Find and define the first argument
|
|
||||||
//
|
|
||||||
Object.defineProperty(args, 'first', { value: args[0] });
|
|
||||||
|
|
||||||
//
|
|
||||||
// Find and define any callback
|
|
||||||
//
|
|
||||||
_cb = args[args.length - 1] || args[args.length];
|
|
||||||
if (typeof _cb === "function") {
|
|
||||||
Object.defineProperty(args, 'callback', { value: _cb });
|
|
||||||
Object.defineProperty(args, 'cb', { value: _cb });
|
|
||||||
args.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Find and define the last argument
|
|
||||||
//
|
|
||||||
if (args.length) {
|
|
||||||
Object.defineProperty(args, 'last', { value: args[args.length - 1] });
|
|
||||||
}
|
|
||||||
|
|
||||||
return args;
|
|
||||||
};
|
|
@ -1,44 +0,0 @@
|
|||||||
/*
|
|
||||||
* base64.js: An extremely simple implementation of base64 encoding / decoding using node.js Buffers
|
|
||||||
*
|
|
||||||
* (C) 2010, Nodejitsu Inc.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
var base64 = exports;
|
|
||||||
|
|
||||||
//
|
|
||||||
// ### function encode (unencoded)
|
|
||||||
// #### @unencoded {string} The string to base64 encode
|
|
||||||
// Encodes the specified string to base64 using node.js Buffers.
|
|
||||||
//
|
|
||||||
base64.encode = function (unencoded) {
|
|
||||||
var encoded;
|
|
||||||
|
|
||||||
try {
|
|
||||||
encoded = new Buffer(unencoded || '').toString('base64');
|
|
||||||
}
|
|
||||||
catch (ex) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return encoded;
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// ### function decode (encoded)
|
|
||||||
// #### @encoded {string} The string to base64 decode
|
|
||||||
// Decodes the specified string from base64 using node.js Buffers.
|
|
||||||
//
|
|
||||||
base64.decode = function (encoded) {
|
|
||||||
var decoded;
|
|
||||||
|
|
||||||
try {
|
|
||||||
decoded = new Buffer(encoded || '', 'base64').toString('utf8');
|
|
||||||
}
|
|
||||||
catch (ex) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return decoded;
|
|
||||||
};
|
|
@ -1,33 +0,0 @@
|
|||||||
/*
|
|
||||||
* file.js: Simple utilities for working with the file system.
|
|
||||||
*
|
|
||||||
* (C) 2011, Nodejitsu Inc.
|
|
||||||
* MIT LICENSE
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
var fs = require('fs');
|
|
||||||
|
|
||||||
exports.readJson = exports.readJSON = function (file, callback) {
|
|
||||||
if (typeof callback !== 'function') {
|
|
||||||
throw new Error('utile.file.readJson needs a callback');
|
|
||||||
}
|
|
||||||
|
|
||||||
fs.readFile(file, 'utf-8', function (err, data) {
|
|
||||||
if (err) {
|
|
||||||
return callback(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
var json = JSON.parse(data);
|
|
||||||
callback(null, json);
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
return callback(err);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.readJsonSync = exports.readJSONSync = function (file) {
|
|
||||||
return JSON.parse(fs.readFileSync(file, 'utf-8'));
|
|
||||||
};
|
|
@ -1,25 +0,0 @@
|
|||||||
/*
|
|
||||||
* format.js: `util.format` enhancement to allow custom formatting parameters.
|
|
||||||
*
|
|
||||||
* (C) 2012, Nodejitsu Inc.
|
|
||||||
* MIT LICENSE
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
var util = require('util');
|
|
||||||
|
|
||||||
exports = module.exports = function(str) {
|
|
||||||
var formats = [].slice.call(arguments, 1, 3);
|
|
||||||
|
|
||||||
if (!(formats[0] instanceof Array && formats[1] instanceof Array) || arguments.length > 3)
|
|
||||||
return util.format.apply(null, arguments);
|
|
||||||
|
|
||||||
var replacements = formats.pop(),
|
|
||||||
formats = formats.shift();
|
|
||||||
|
|
||||||
formats.forEach(function(format, id) {
|
|
||||||
str = str.replace(new RegExp(format), replacements[id]);
|
|
||||||
});
|
|
||||||
|
|
||||||
return str;
|
|
||||||
};
|
|
@ -1,467 +0,0 @@
|
|||||||
/*
|
|
||||||
* index.js: Top-level include for the `utile` module.
|
|
||||||
*
|
|
||||||
* (C) 2011, Nodejitsu Inc.
|
|
||||||
* MIT LICENSE
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
var fs = require('fs'),
|
|
||||||
path = require('path'),
|
|
||||||
util = require('util');
|
|
||||||
|
|
||||||
var utile = module.exports;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Extend the `utile` object with all methods from the
|
|
||||||
// core node `util` methods.
|
|
||||||
//
|
|
||||||
Object.keys(util).forEach(function (key) {
|
|
||||||
utile[key] = util[key];
|
|
||||||
});
|
|
||||||
|
|
||||||
Object.defineProperties(utile, {
|
|
||||||
|
|
||||||
//
|
|
||||||
// ### function async
|
|
||||||
// Simple wrapper to `require('async')`.
|
|
||||||
//
|
|
||||||
'async': {
|
|
||||||
get: function() {
|
|
||||||
return utile.async = require('async');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
//
|
|
||||||
// ### function inflect
|
|
||||||
// Simple wrapper to `require('i')`.
|
|
||||||
//
|
|
||||||
'inflect': {
|
|
||||||
get: function() {
|
|
||||||
return utile.inflect = require('i')();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
//
|
|
||||||
// ### function mkdirp
|
|
||||||
// Simple wrapper to `require('mkdirp')`
|
|
||||||
//
|
|
||||||
'mkdirp': {
|
|
||||||
get: function() {
|
|
||||||
return utile.mkdirp = require('mkdirp');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
//
|
|
||||||
// ### function deepEqual
|
|
||||||
// Simple wrapper to `require('deep-equal')`
|
|
||||||
// Remark: deepEqual is 4x faster then using assert.deepEqual
|
|
||||||
// see: https://gist.github.com/2790507
|
|
||||||
//
|
|
||||||
'deepEqual': {
|
|
||||||
get: function() {
|
|
||||||
return utile.deepEqual = require('deep-equal');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
//
|
|
||||||
// ### function rimraf
|
|
||||||
// Simple wrapper to `require('rimraf')`
|
|
||||||
//
|
|
||||||
'rimraf': {
|
|
||||||
get: function() {
|
|
||||||
return utile.rimraf = require('rimraf');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
//
|
|
||||||
// ### function cpr
|
|
||||||
// Simple wrapper to `require('ncp').ncp`
|
|
||||||
//
|
|
||||||
'cpr': {
|
|
||||||
get: function() {
|
|
||||||
return utile.cpr = require('ncp').ncp;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
//
|
|
||||||
// ### @file {Object}
|
|
||||||
// Lazy-loaded `file` module
|
|
||||||
//
|
|
||||||
'file': {
|
|
||||||
get: function() {
|
|
||||||
return utile.file = require('./file');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
//
|
|
||||||
// ### @args {Object}
|
|
||||||
// Lazy-loaded `args` module
|
|
||||||
//
|
|
||||||
'args': {
|
|
||||||
get: function() {
|
|
||||||
return utile.args = require('./args');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
//
|
|
||||||
// ### @base64 {Object}
|
|
||||||
// Lazy-loaded `base64` object
|
|
||||||
//
|
|
||||||
'base64': {
|
|
||||||
get: function() {
|
|
||||||
return utile.base64 = require('./base64');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
//
|
|
||||||
// ### @format {Object}
|
|
||||||
// Lazy-loaded `format` object
|
|
||||||
//
|
|
||||||
'format': {
|
|
||||||
get: function() {
|
|
||||||
return utile.format = require('./format');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// ### function rargs(_args)
|
|
||||||
// #### _args {Arguments} Original function arguments
|
|
||||||
//
|
|
||||||
// Top-level method will accept a javascript "arguments" object
|
|
||||||
// (the actual keyword "arguments" inside any scope) and return
|
|
||||||
// back an Array.
|
|
||||||
//
|
|
||||||
utile.rargs = function (_args, slice) {
|
|
||||||
if (!slice) {
|
|
||||||
slice = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
var len = (_args || []).length,
|
|
||||||
args = new Array(len - slice),
|
|
||||||
i;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Convert the raw `_args` to a proper Array.
|
|
||||||
//
|
|
||||||
for (i = slice; i < len; i++) {
|
|
||||||
args[i - slice] = _args[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
return args;
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// ### function each (obj, iterator)
|
|
||||||
// #### @obj {Object} Object to iterate over
|
|
||||||
// #### @iterator {function} Continuation to use on each key. `function (value, key, object)`
|
|
||||||
// Iterate over the keys of an object.
|
|
||||||
//
|
|
||||||
utile.each = function (obj, iterator) {
|
|
||||||
Object.keys(obj).forEach(function (key) {
|
|
||||||
iterator(obj[key], key, obj);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// ### function find (o)
|
|
||||||
//
|
|
||||||
//
|
|
||||||
utile.find = function (obj, pred) {
|
|
||||||
var value, key;
|
|
||||||
|
|
||||||
for (key in obj) {
|
|
||||||
value = obj[key];
|
|
||||||
if (pred(value, key)) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// ### function pad (str, len, chr)
|
|
||||||
// ### @str {String} String to pad
|
|
||||||
// ### @len {Number} Number of chars to pad str with
|
|
||||||
// ### @chr {String} Optional replacement character, defaults to empty space
|
|
||||||
// Appends chr to str until it reaches a length of len
|
|
||||||
//
|
|
||||||
utile.pad = function pad(str, len, chr) {
|
|
||||||
var s;
|
|
||||||
if (!chr) {
|
|
||||||
chr = ' ';
|
|
||||||
}
|
|
||||||
str = str || '';
|
|
||||||
s = str;
|
|
||||||
if (str.length < len) {
|
|
||||||
for (var i = 0; i < (len - str.length); i++) {
|
|
||||||
s += chr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// ### function path (obj, path, value)
|
|
||||||
// ### @obj {Object} Object to insert value into
|
|
||||||
// ### @path {Array} List of nested keys to insert value at
|
|
||||||
// Retreives a value from given Object, `obj`, located at the
|
|
||||||
// nested keys, `path`.
|
|
||||||
//
|
|
||||||
utile.path = function (obj, path) {
|
|
||||||
var key, i;
|
|
||||||
|
|
||||||
for (i in path) {
|
|
||||||
if (typeof obj === 'undefined') {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
key = path[i];
|
|
||||||
obj = obj[key];
|
|
||||||
}
|
|
||||||
|
|
||||||
return obj;
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// ### function createPath (obj, path, value)
|
|
||||||
// ### @obj {Object} Object to insert value into
|
|
||||||
// ### @path {Array} List of nested keys to insert value at
|
|
||||||
// ### @value {*} Value to insert into the object.
|
|
||||||
// Inserts the `value` into the given Object, `obj`, creating
|
|
||||||
// any keys in `path` along the way if necessary.
|
|
||||||
//
|
|
||||||
utile.createPath = function (obj, path, value) {
|
|
||||||
var key, i;
|
|
||||||
|
|
||||||
for (i in path) {
|
|
||||||
key = path[i];
|
|
||||||
if (!obj[key]) {
|
|
||||||
obj[key] = ((+i + 1 === path.length) ? value : {});
|
|
||||||
}
|
|
||||||
|
|
||||||
obj = obj[key];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// ### function mixin (target [source0, source1, ...])
|
|
||||||
// Copies enumerable properties from `source0 ... sourceN`
|
|
||||||
// onto `target` and returns the resulting object.
|
|
||||||
//
|
|
||||||
utile.mixin = function (target) {
|
|
||||||
utile.rargs(arguments, 1).forEach(function (o) {
|
|
||||||
Object.getOwnPropertyNames(o).forEach(function(attr) {
|
|
||||||
var getter = Object.getOwnPropertyDescriptor(o, attr).get,
|
|
||||||
setter = Object.getOwnPropertyDescriptor(o, attr).set;
|
|
||||||
|
|
||||||
if (!getter && !setter) {
|
|
||||||
target[attr] = o[attr];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Object.defineProperty(target, attr, {
|
|
||||||
get: getter,
|
|
||||||
set: setter
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return target;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// ### function capitalize (str)
|
|
||||||
// #### @str {string} String to capitalize
|
|
||||||
// Capitalizes the specified `str`.
|
|
||||||
//
|
|
||||||
utile.capitalize = utile.inflect.camelize;
|
|
||||||
|
|
||||||
//
|
|
||||||
// ### function escapeRegExp (str)
|
|
||||||
// #### @str {string} String to be escaped
|
|
||||||
// Escape string for use in Javascript regex
|
|
||||||
//
|
|
||||||
utile.escapeRegExp = function (str) {
|
|
||||||
return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// ### function randomString (length)
|
|
||||||
// #### @length {integer} The number of bits for the random base64 string returned to contain
|
|
||||||
// randomString returns a pseude-random ASCII string (subset)
|
|
||||||
// the return value is a string of length ⌈bits/6⌉ of characters
|
|
||||||
// from the base64 alphabet.
|
|
||||||
//
|
|
||||||
utile.randomString = function (length) {
|
|
||||||
var chars, rand, i, ret, mod, bits;
|
|
||||||
|
|
||||||
chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-';
|
|
||||||
ret = '';
|
|
||||||
// standard 4
|
|
||||||
mod = 4;
|
|
||||||
// default is 16
|
|
||||||
bits = length * mod || 64;
|
|
||||||
|
|
||||||
// in v8, Math.random() yields 32 pseudo-random bits (in spidermonkey it gives 53)
|
|
||||||
while (bits > 0) {
|
|
||||||
// 32-bit integer
|
|
||||||
rand = Math.floor(Math.random() * 0x100000000);
|
|
||||||
//we use the top bits
|
|
||||||
for (i = 26; i > 0 && bits > 0; i -= mod, bits -= mod) {
|
|
||||||
ret += chars[0x3F & rand >>> i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// ### function filter (object, test)
|
|
||||||
// #### @obj {Object} Object to iterate over
|
|
||||||
// #### @pred {function} Predicate applied to each property. `function (value, key, object)`
|
|
||||||
// Returns an object with properties from `obj` which satisfy
|
|
||||||
// the predicate `pred`
|
|
||||||
//
|
|
||||||
utile.filter = function (obj, pred) {
|
|
||||||
var copy;
|
|
||||||
if (Array.isArray(obj)) {
|
|
||||||
copy = [];
|
|
||||||
utile.each(obj, function (val, key) {
|
|
||||||
if (pred(val, key, obj)) {
|
|
||||||
copy.push(val);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
copy = {};
|
|
||||||
utile.each(obj, function (val, key) {
|
|
||||||
if (pred(val, key, obj)) {
|
|
||||||
copy[key] = val;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return copy;
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// ### function requireDir (directory)
|
|
||||||
// #### @directory {string} Directory to require
|
|
||||||
// Requires all files and directories from `directory`, returning an object
|
|
||||||
// with keys being filenames (without trailing `.js`) and respective values
|
|
||||||
// being return values of `require(filename)`.
|
|
||||||
//
|
|
||||||
utile.requireDir = function (directory) {
|
|
||||||
var result = {},
|
|
||||||
files = fs.readdirSync(directory);
|
|
||||||
|
|
||||||
files.forEach(function (file) {
|
|
||||||
if (file.substr(-3) === '.js') {
|
|
||||||
file = file.substr(0, file.length - 3);
|
|
||||||
}
|
|
||||||
result[file] = require(path.resolve(directory, file));
|
|
||||||
});
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// ### function requireDirLazy (directory)
|
|
||||||
// #### @directory {string} Directory to require
|
|
||||||
// Lazily requires all files and directories from `directory`, returning an
|
|
||||||
// object with keys being filenames (without trailing `.js`) and respective
|
|
||||||
// values (getters) being return values of `require(filename)`.
|
|
||||||
//
|
|
||||||
utile.requireDirLazy = function (directory) {
|
|
||||||
var result = {},
|
|
||||||
files = fs.readdirSync(directory);
|
|
||||||
|
|
||||||
files.forEach(function (file) {
|
|
||||||
if (file.substr(-3) === '.js') {
|
|
||||||
file = file.substr(0, file.length - 3);
|
|
||||||
}
|
|
||||||
Object.defineProperty(result, file, {
|
|
||||||
get: function() {
|
|
||||||
return result[file] = require(path.resolve(directory, file));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// ### function clone (object, filter)
|
|
||||||
// #### @object {Object} Object to clone
|
|
||||||
// #### @filter {Function} Filter to be used
|
|
||||||
// Shallow clones the specified object.
|
|
||||||
//
|
|
||||||
utile.clone = function (object, filter) {
|
|
||||||
return Object.keys(object).reduce(filter ? function (obj, k) {
|
|
||||||
if (filter(k)) obj[k] = object[k];
|
|
||||||
return obj;
|
|
||||||
} : function (obj, k) {
|
|
||||||
obj[k] = object[k];
|
|
||||||
return obj;
|
|
||||||
}, {});
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// ### function camelToUnderscore (obj)
|
|
||||||
// #### @obj {Object} Object to convert keys on.
|
|
||||||
// Converts all keys of the type `keyName` to `key_name` on the
|
|
||||||
// specified `obj`.
|
|
||||||
//
|
|
||||||
utile.camelToUnderscore = function (obj) {
|
|
||||||
if (typeof obj !== 'object' || obj === null) {
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Array.isArray(obj)) {
|
|
||||||
obj.forEach(utile.camelToUnderscore);
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
Object.keys(obj).forEach(function (key) {
|
|
||||||
var k = utile.inflect.underscore(key);
|
|
||||||
if (k !== key) {
|
|
||||||
obj[k] = obj[key];
|
|
||||||
delete obj[key];
|
|
||||||
key = k;
|
|
||||||
}
|
|
||||||
utile.camelToUnderscore(obj[key]);
|
|
||||||
});
|
|
||||||
|
|
||||||
return obj;
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// ### function underscoreToCamel (obj)
|
|
||||||
// #### @obj {Object} Object to convert keys on.
|
|
||||||
// Converts all keys of the type `key_name` to `keyName` on the
|
|
||||||
// specified `obj`.
|
|
||||||
//
|
|
||||||
utile.underscoreToCamel = function (obj) {
|
|
||||||
if (typeof obj !== 'object' || obj === null) {
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Array.isArray(obj)) {
|
|
||||||
obj.forEach(utile.underscoreToCamel);
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
Object.keys(obj).forEach(function (key) {
|
|
||||||
var k = utile.inflect.camelize(key, false);
|
|
||||||
if (k !== key) {
|
|
||||||
obj[k] = obj[key];
|
|
||||||
delete obj[key];
|
|
||||||
key = k;
|
|
||||||
}
|
|
||||||
utile.underscoreToCamel(obj[key]);
|
|
||||||
});
|
|
||||||
|
|
||||||
return obj;
|
|
||||||
};
|
|
@ -1 +0,0 @@
|
|||||||
../mkdirp/bin/cmd.js
|
|
@ -1 +0,0 @@
|
|||||||
../ncp/bin/ncp
|
|
@ -1 +0,0 @@
|
|||||||
../rimraf/bin.js
|
|
@ -1,19 +0,0 @@
|
|||||||
Copyright (c) 2010 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
@ -1,11 +0,0 @@
|
|||||||
{
|
|
||||||
"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" ]
|
|
||||||
}
|
|
@ -1,958 +0,0 @@
|
|||||||
/*global setImmediate: false, setTimeout: false, console: false */
|
|
||||||
(function () {
|
|
||||||
|
|
||||||
var async = {};
|
|
||||||
|
|
||||||
// global on the server, window in the browser
|
|
||||||
var root, previous_async;
|
|
||||||
|
|
||||||
root = this;
|
|
||||||
if (root != null) {
|
|
||||||
previous_async = root.async;
|
|
||||||
}
|
|
||||||
|
|
||||||
async.noConflict = function () {
|
|
||||||
root.async = previous_async;
|
|
||||||
return async;
|
|
||||||
};
|
|
||||||
|
|
||||||
function only_once(fn) {
|
|
||||||
var called = false;
|
|
||||||
return function() {
|
|
||||||
if (called) throw new Error("Callback was already called.");
|
|
||||||
called = true;
|
|
||||||
fn.apply(root, arguments);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//// cross-browser compatiblity functions ////
|
|
||||||
|
|
||||||
var _each = function (arr, iterator) {
|
|
||||||
if (arr.forEach) {
|
|
||||||
return arr.forEach(iterator);
|
|
||||||
}
|
|
||||||
for (var i = 0; i < arr.length; i += 1) {
|
|
||||||
iterator(arr[i], i, arr);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var _map = function (arr, iterator) {
|
|
||||||
if (arr.map) {
|
|
||||||
return arr.map(iterator);
|
|
||||||
}
|
|
||||||
var results = [];
|
|
||||||
_each(arr, function (x, i, a) {
|
|
||||||
results.push(iterator(x, i, a));
|
|
||||||
});
|
|
||||||
return results;
|
|
||||||
};
|
|
||||||
|
|
||||||
var _reduce = function (arr, iterator, memo) {
|
|
||||||
if (arr.reduce) {
|
|
||||||
return arr.reduce(iterator, memo);
|
|
||||||
}
|
|
||||||
_each(arr, function (x, i, a) {
|
|
||||||
memo = iterator(memo, x, i, a);
|
|
||||||
});
|
|
||||||
return memo;
|
|
||||||
};
|
|
||||||
|
|
||||||
var _keys = function (obj) {
|
|
||||||
if (Object.keys) {
|
|
||||||
return Object.keys(obj);
|
|
||||||
}
|
|
||||||
var keys = [];
|
|
||||||
for (var k in obj) {
|
|
||||||
if (obj.hasOwnProperty(k)) {
|
|
||||||
keys.push(k);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return keys;
|
|
||||||
};
|
|
||||||
|
|
||||||
//// exported async module functions ////
|
|
||||||
|
|
||||||
//// nextTick implementation with browser-compatible fallback ////
|
|
||||||
if (typeof process === 'undefined' || !(process.nextTick)) {
|
|
||||||
if (typeof setImmediate === 'function') {
|
|
||||||
async.nextTick = function (fn) {
|
|
||||||
// not a direct alias for IE10 compatibility
|
|
||||||
setImmediate(fn);
|
|
||||||
};
|
|
||||||
async.setImmediate = async.nextTick;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
async.nextTick = function (fn) {
|
|
||||||
setTimeout(fn, 0);
|
|
||||||
};
|
|
||||||
async.setImmediate = async.nextTick;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
async.nextTick = process.nextTick;
|
|
||||||
if (typeof setImmediate !== 'undefined') {
|
|
||||||
async.setImmediate = function (fn) {
|
|
||||||
// not a direct alias for IE10 compatibility
|
|
||||||
setImmediate(fn);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
async.setImmediate = async.nextTick;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async.each = function (arr, iterator, callback) {
|
|
||||||
callback = callback || function () {};
|
|
||||||
if (!arr.length) {
|
|
||||||
return callback();
|
|
||||||
}
|
|
||||||
var completed = 0;
|
|
||||||
_each(arr, function (x) {
|
|
||||||
iterator(x, only_once(function (err) {
|
|
||||||
if (err) {
|
|
||||||
callback(err);
|
|
||||||
callback = function () {};
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
completed += 1;
|
|
||||||
if (completed >= arr.length) {
|
|
||||||
callback(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
async.forEach = async.each;
|
|
||||||
|
|
||||||
async.eachSeries = function (arr, iterator, callback) {
|
|
||||||
callback = callback || function () {};
|
|
||||||
if (!arr.length) {
|
|
||||||
return callback();
|
|
||||||
}
|
|
||||||
var completed = 0;
|
|
||||||
var iterate = function () {
|
|
||||||
iterator(arr[completed], function (err) {
|
|
||||||
if (err) {
|
|
||||||
callback(err);
|
|
||||||
callback = function () {};
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
completed += 1;
|
|
||||||
if (completed >= arr.length) {
|
|
||||||
callback(null);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
iterate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
iterate();
|
|
||||||
};
|
|
||||||
async.forEachSeries = async.eachSeries;
|
|
||||||
|
|
||||||
async.eachLimit = function (arr, limit, iterator, callback) {
|
|
||||||
var fn = _eachLimit(limit);
|
|
||||||
fn.apply(null, [arr, iterator, callback]);
|
|
||||||
};
|
|
||||||
async.forEachLimit = async.eachLimit;
|
|
||||||
|
|
||||||
var _eachLimit = function (limit) {
|
|
||||||
|
|
||||||
return function (arr, iterator, callback) {
|
|
||||||
callback = callback || function () {};
|
|
||||||
if (!arr.length || limit <= 0) {
|
|
||||||
return callback();
|
|
||||||
}
|
|
||||||
var completed = 0;
|
|
||||||
var started = 0;
|
|
||||||
var running = 0;
|
|
||||||
|
|
||||||
(function replenish () {
|
|
||||||
if (completed >= arr.length) {
|
|
||||||
return callback();
|
|
||||||
}
|
|
||||||
|
|
||||||
while (running < limit && started < arr.length) {
|
|
||||||
started += 1;
|
|
||||||
running += 1;
|
|
||||||
iterator(arr[started - 1], function (err) {
|
|
||||||
if (err) {
|
|
||||||
callback(err);
|
|
||||||
callback = function () {};
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
completed += 1;
|
|
||||||
running -= 1;
|
|
||||||
if (completed >= arr.length) {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
replenish();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
var doParallel = function (fn) {
|
|
||||||
return function () {
|
|
||||||
var args = Array.prototype.slice.call(arguments);
|
|
||||||
return fn.apply(null, [async.each].concat(args));
|
|
||||||
};
|
|
||||||
};
|
|
||||||
var doParallelLimit = function(limit, fn) {
|
|
||||||
return function () {
|
|
||||||
var args = Array.prototype.slice.call(arguments);
|
|
||||||
return fn.apply(null, [_eachLimit(limit)].concat(args));
|
|
||||||
};
|
|
||||||
};
|
|
||||||
var doSeries = function (fn) {
|
|
||||||
return function () {
|
|
||||||
var args = Array.prototype.slice.call(arguments);
|
|
||||||
return fn.apply(null, [async.eachSeries].concat(args));
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
var _asyncMap = function (eachfn, arr, iterator, callback) {
|
|
||||||
var results = [];
|
|
||||||
arr = _map(arr, function (x, i) {
|
|
||||||
return {index: i, value: x};
|
|
||||||
});
|
|
||||||
eachfn(arr, function (x, callback) {
|
|
||||||
iterator(x.value, function (err, v) {
|
|
||||||
results[x.index] = v;
|
|
||||||
callback(err);
|
|
||||||
});
|
|
||||||
}, function (err) {
|
|
||||||
callback(err, results);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
async.map = doParallel(_asyncMap);
|
|
||||||
async.mapSeries = doSeries(_asyncMap);
|
|
||||||
async.mapLimit = function (arr, limit, iterator, callback) {
|
|
||||||
return _mapLimit(limit)(arr, iterator, callback);
|
|
||||||
};
|
|
||||||
|
|
||||||
var _mapLimit = function(limit) {
|
|
||||||
return doParallelLimit(limit, _asyncMap);
|
|
||||||
};
|
|
||||||
|
|
||||||
// reduce only has a series version, as doing reduce in parallel won't
|
|
||||||
// work in many situations.
|
|
||||||
async.reduce = function (arr, memo, iterator, callback) {
|
|
||||||
async.eachSeries(arr, function (x, callback) {
|
|
||||||
iterator(memo, x, function (err, v) {
|
|
||||||
memo = v;
|
|
||||||
callback(err);
|
|
||||||
});
|
|
||||||
}, function (err) {
|
|
||||||
callback(err, memo);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
// inject alias
|
|
||||||
async.inject = async.reduce;
|
|
||||||
// foldl alias
|
|
||||||
async.foldl = async.reduce;
|
|
||||||
|
|
||||||
async.reduceRight = function (arr, memo, iterator, callback) {
|
|
||||||
var reversed = _map(arr, function (x) {
|
|
||||||
return x;
|
|
||||||
}).reverse();
|
|
||||||
async.reduce(reversed, memo, iterator, callback);
|
|
||||||
};
|
|
||||||
// foldr alias
|
|
||||||
async.foldr = async.reduceRight;
|
|
||||||
|
|
||||||
var _filter = function (eachfn, arr, iterator, callback) {
|
|
||||||
var results = [];
|
|
||||||
arr = _map(arr, function (x, i) {
|
|
||||||
return {index: i, value: x};
|
|
||||||
});
|
|
||||||
eachfn(arr, function (x, callback) {
|
|
||||||
iterator(x.value, function (v) {
|
|
||||||
if (v) {
|
|
||||||
results.push(x);
|
|
||||||
}
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
}, function (err) {
|
|
||||||
callback(_map(results.sort(function (a, b) {
|
|
||||||
return a.index - b.index;
|
|
||||||
}), function (x) {
|
|
||||||
return x.value;
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
async.filter = doParallel(_filter);
|
|
||||||
async.filterSeries = doSeries(_filter);
|
|
||||||
// select alias
|
|
||||||
async.select = async.filter;
|
|
||||||
async.selectSeries = async.filterSeries;
|
|
||||||
|
|
||||||
var _reject = function (eachfn, arr, iterator, callback) {
|
|
||||||
var results = [];
|
|
||||||
arr = _map(arr, function (x, i) {
|
|
||||||
return {index: i, value: x};
|
|
||||||
});
|
|
||||||
eachfn(arr, function (x, callback) {
|
|
||||||
iterator(x.value, function (v) {
|
|
||||||
if (!v) {
|
|
||||||
results.push(x);
|
|
||||||
}
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
}, function (err) {
|
|
||||||
callback(_map(results.sort(function (a, b) {
|
|
||||||
return a.index - b.index;
|
|
||||||
}), function (x) {
|
|
||||||
return x.value;
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
async.reject = doParallel(_reject);
|
|
||||||
async.rejectSeries = doSeries(_reject);
|
|
||||||
|
|
||||||
var _detect = function (eachfn, arr, iterator, main_callback) {
|
|
||||||
eachfn(arr, function (x, callback) {
|
|
||||||
iterator(x, function (result) {
|
|
||||||
if (result) {
|
|
||||||
main_callback(x);
|
|
||||||
main_callback = function () {};
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, function (err) {
|
|
||||||
main_callback();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
async.detect = doParallel(_detect);
|
|
||||||
async.detectSeries = doSeries(_detect);
|
|
||||||
|
|
||||||
async.some = function (arr, iterator, main_callback) {
|
|
||||||
async.each(arr, function (x, callback) {
|
|
||||||
iterator(x, function (v) {
|
|
||||||
if (v) {
|
|
||||||
main_callback(true);
|
|
||||||
main_callback = function () {};
|
|
||||||
}
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
}, function (err) {
|
|
||||||
main_callback(false);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
// any alias
|
|
||||||
async.any = async.some;
|
|
||||||
|
|
||||||
async.every = function (arr, iterator, main_callback) {
|
|
||||||
async.each(arr, function (x, callback) {
|
|
||||||
iterator(x, function (v) {
|
|
||||||
if (!v) {
|
|
||||||
main_callback(false);
|
|
||||||
main_callback = function () {};
|
|
||||||
}
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
}, function (err) {
|
|
||||||
main_callback(true);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
// all alias
|
|
||||||
async.all = async.every;
|
|
||||||
|
|
||||||
async.sortBy = function (arr, iterator, callback) {
|
|
||||||
async.map(arr, function (x, callback) {
|
|
||||||
iterator(x, function (err, criteria) {
|
|
||||||
if (err) {
|
|
||||||
callback(err);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
callback(null, {value: x, criteria: criteria});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, function (err, results) {
|
|
||||||
if (err) {
|
|
||||||
return callback(err);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
var fn = function (left, right) {
|
|
||||||
var a = left.criteria, b = right.criteria;
|
|
||||||
return a < b ? -1 : a > b ? 1 : 0;
|
|
||||||
};
|
|
||||||
callback(null, _map(results.sort(fn), function (x) {
|
|
||||||
return x.value;
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
async.auto = function (tasks, callback) {
|
|
||||||
callback = callback || function () {};
|
|
||||||
var keys = _keys(tasks);
|
|
||||||
if (!keys.length) {
|
|
||||||
return callback(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
var results = {};
|
|
||||||
|
|
||||||
var listeners = [];
|
|
||||||
var addListener = function (fn) {
|
|
||||||
listeners.unshift(fn);
|
|
||||||
};
|
|
||||||
var removeListener = function (fn) {
|
|
||||||
for (var i = 0; i < listeners.length; i += 1) {
|
|
||||||
if (listeners[i] === fn) {
|
|
||||||
listeners.splice(i, 1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
var taskComplete = function () {
|
|
||||||
_each(listeners.slice(0), function (fn) {
|
|
||||||
fn();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
addListener(function () {
|
|
||||||
if (_keys(results).length === keys.length) {
|
|
||||||
callback(null, results);
|
|
||||||
callback = function () {};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
_each(keys, function (k) {
|
|
||||||
var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k];
|
|
||||||
var taskCallback = function (err) {
|
|
||||||
var args = Array.prototype.slice.call(arguments, 1);
|
|
||||||
if (args.length <= 1) {
|
|
||||||
args = args[0];
|
|
||||||
}
|
|
||||||
if (err) {
|
|
||||||
var safeResults = {};
|
|
||||||
_each(_keys(results), function(rkey) {
|
|
||||||
safeResults[rkey] = results[rkey];
|
|
||||||
});
|
|
||||||
safeResults[k] = args;
|
|
||||||
callback(err, safeResults);
|
|
||||||
// stop subsequent errors hitting callback multiple times
|
|
||||||
callback = function () {};
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
results[k] = args;
|
|
||||||
async.setImmediate(taskComplete);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
var requires = task.slice(0, Math.abs(task.length - 1)) || [];
|
|
||||||
var ready = function () {
|
|
||||||
return _reduce(requires, function (a, x) {
|
|
||||||
return (a && results.hasOwnProperty(x));
|
|
||||||
}, true) && !results.hasOwnProperty(k);
|
|
||||||
};
|
|
||||||
if (ready()) {
|
|
||||||
task[task.length - 1](taskCallback, results);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
var listener = function () {
|
|
||||||
if (ready()) {
|
|
||||||
removeListener(listener);
|
|
||||||
task[task.length - 1](taskCallback, results);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
addListener(listener);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
async.waterfall = function (tasks, callback) {
|
|
||||||
callback = callback || function () {};
|
|
||||||
if (tasks.constructor !== Array) {
|
|
||||||
var err = new Error('First argument to waterfall must be an array of functions');
|
|
||||||
return callback(err);
|
|
||||||
}
|
|
||||||
if (!tasks.length) {
|
|
||||||
return callback();
|
|
||||||
}
|
|
||||||
var wrapIterator = function (iterator) {
|
|
||||||
return function (err) {
|
|
||||||
if (err) {
|
|
||||||
callback.apply(null, arguments);
|
|
||||||
callback = function () {};
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
var args = Array.prototype.slice.call(arguments, 1);
|
|
||||||
var next = iterator.next();
|
|
||||||
if (next) {
|
|
||||||
args.push(wrapIterator(next));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
args.push(callback);
|
|
||||||
}
|
|
||||||
async.setImmediate(function () {
|
|
||||||
iterator.apply(null, args);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
wrapIterator(async.iterator(tasks))();
|
|
||||||
};
|
|
||||||
|
|
||||||
var _parallel = function(eachfn, tasks, callback) {
|
|
||||||
callback = callback || function () {};
|
|
||||||
if (tasks.constructor === Array) {
|
|
||||||
eachfn.map(tasks, function (fn, callback) {
|
|
||||||
if (fn) {
|
|
||||||
fn(function (err) {
|
|
||||||
var args = Array.prototype.slice.call(arguments, 1);
|
|
||||||
if (args.length <= 1) {
|
|
||||||
args = args[0];
|
|
||||||
}
|
|
||||||
callback.call(null, err, args);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, callback);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
var results = {};
|
|
||||||
eachfn.each(_keys(tasks), function (k, callback) {
|
|
||||||
tasks[k](function (err) {
|
|
||||||
var args = Array.prototype.slice.call(arguments, 1);
|
|
||||||
if (args.length <= 1) {
|
|
||||||
args = args[0];
|
|
||||||
}
|
|
||||||
results[k] = args;
|
|
||||||
callback(err);
|
|
||||||
});
|
|
||||||
}, function (err) {
|
|
||||||
callback(err, results);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
async.parallel = function (tasks, callback) {
|
|
||||||
_parallel({ map: async.map, each: async.each }, tasks, callback);
|
|
||||||
};
|
|
||||||
|
|
||||||
async.parallelLimit = function(tasks, limit, callback) {
|
|
||||||
_parallel({ map: _mapLimit(limit), each: _eachLimit(limit) }, tasks, callback);
|
|
||||||
};
|
|
||||||
|
|
||||||
async.series = function (tasks, callback) {
|
|
||||||
callback = callback || function () {};
|
|
||||||
if (tasks.constructor === Array) {
|
|
||||||
async.mapSeries(tasks, function (fn, callback) {
|
|
||||||
if (fn) {
|
|
||||||
fn(function (err) {
|
|
||||||
var args = Array.prototype.slice.call(arguments, 1);
|
|
||||||
if (args.length <= 1) {
|
|
||||||
args = args[0];
|
|
||||||
}
|
|
||||||
callback.call(null, err, args);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, callback);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
var results = {};
|
|
||||||
async.eachSeries(_keys(tasks), function (k, callback) {
|
|
||||||
tasks[k](function (err) {
|
|
||||||
var args = Array.prototype.slice.call(arguments, 1);
|
|
||||||
if (args.length <= 1) {
|
|
||||||
args = args[0];
|
|
||||||
}
|
|
||||||
results[k] = args;
|
|
||||||
callback(err);
|
|
||||||
});
|
|
||||||
}, function (err) {
|
|
||||||
callback(err, results);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
async.iterator = function (tasks) {
|
|
||||||
var makeCallback = function (index) {
|
|
||||||
var fn = function () {
|
|
||||||
if (tasks.length) {
|
|
||||||
tasks[index].apply(null, arguments);
|
|
||||||
}
|
|
||||||
return fn.next();
|
|
||||||
};
|
|
||||||
fn.next = function () {
|
|
||||||
return (index < tasks.length - 1) ? makeCallback(index + 1): null;
|
|
||||||
};
|
|
||||||
return fn;
|
|
||||||
};
|
|
||||||
return makeCallback(0);
|
|
||||||
};
|
|
||||||
|
|
||||||
async.apply = function (fn) {
|
|
||||||
var args = Array.prototype.slice.call(arguments, 1);
|
|
||||||
return function () {
|
|
||||||
return fn.apply(
|
|
||||||
null, args.concat(Array.prototype.slice.call(arguments))
|
|
||||||
);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
var _concat = function (eachfn, arr, fn, callback) {
|
|
||||||
var r = [];
|
|
||||||
eachfn(arr, function (x, cb) {
|
|
||||||
fn(x, function (err, y) {
|
|
||||||
r = r.concat(y || []);
|
|
||||||
cb(err);
|
|
||||||
});
|
|
||||||
}, function (err) {
|
|
||||||
callback(err, r);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
async.concat = doParallel(_concat);
|
|
||||||
async.concatSeries = doSeries(_concat);
|
|
||||||
|
|
||||||
async.whilst = function (test, iterator, callback) {
|
|
||||||
if (test()) {
|
|
||||||
iterator(function (err) {
|
|
||||||
if (err) {
|
|
||||||
return callback(err);
|
|
||||||
}
|
|
||||||
async.whilst(test, iterator, callback);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
async.doWhilst = function (iterator, test, callback) {
|
|
||||||
iterator(function (err) {
|
|
||||||
if (err) {
|
|
||||||
return callback(err);
|
|
||||||
}
|
|
||||||
if (test()) {
|
|
||||||
async.doWhilst(iterator, test, callback);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
async.until = function (test, iterator, callback) {
|
|
||||||
if (!test()) {
|
|
||||||
iterator(function (err) {
|
|
||||||
if (err) {
|
|
||||||
return callback(err);
|
|
||||||
}
|
|
||||||
async.until(test, iterator, callback);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
async.doUntil = function (iterator, test, callback) {
|
|
||||||
iterator(function (err) {
|
|
||||||
if (err) {
|
|
||||||
return callback(err);
|
|
||||||
}
|
|
||||||
if (!test()) {
|
|
||||||
async.doUntil(iterator, test, callback);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
async.queue = function (worker, concurrency) {
|
|
||||||
if (concurrency === undefined) {
|
|
||||||
concurrency = 1;
|
|
||||||
}
|
|
||||||
function _insert(q, data, pos, callback) {
|
|
||||||
if(data.constructor !== Array) {
|
|
||||||
data = [data];
|
|
||||||
}
|
|
||||||
_each(data, function(task) {
|
|
||||||
var item = {
|
|
||||||
data: task,
|
|
||||||
callback: typeof callback === 'function' ? callback : null
|
|
||||||
};
|
|
||||||
|
|
||||||
if (pos) {
|
|
||||||
q.tasks.unshift(item);
|
|
||||||
} else {
|
|
||||||
q.tasks.push(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (q.saturated && q.tasks.length === concurrency) {
|
|
||||||
q.saturated();
|
|
||||||
}
|
|
||||||
async.setImmediate(q.process);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
var workers = 0;
|
|
||||||
var q = {
|
|
||||||
tasks: [],
|
|
||||||
concurrency: concurrency,
|
|
||||||
saturated: null,
|
|
||||||
empty: null,
|
|
||||||
drain: null,
|
|
||||||
push: function (data, callback) {
|
|
||||||
_insert(q, data, false, callback);
|
|
||||||
},
|
|
||||||
unshift: function (data, callback) {
|
|
||||||
_insert(q, data, true, callback);
|
|
||||||
},
|
|
||||||
process: function () {
|
|
||||||
if (workers < q.concurrency && q.tasks.length) {
|
|
||||||
var task = q.tasks.shift();
|
|
||||||
if (q.empty && q.tasks.length === 0) {
|
|
||||||
q.empty();
|
|
||||||
}
|
|
||||||
workers += 1;
|
|
||||||
var next = function () {
|
|
||||||
workers -= 1;
|
|
||||||
if (task.callback) {
|
|
||||||
task.callback.apply(task, arguments);
|
|
||||||
}
|
|
||||||
if (q.drain && q.tasks.length + workers === 0) {
|
|
||||||
q.drain();
|
|
||||||
}
|
|
||||||
q.process();
|
|
||||||
};
|
|
||||||
var cb = only_once(next);
|
|
||||||
worker(task.data, cb);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
length: function () {
|
|
||||||
return q.tasks.length;
|
|
||||||
},
|
|
||||||
running: function () {
|
|
||||||
return workers;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return q;
|
|
||||||
};
|
|
||||||
|
|
||||||
async.cargo = function (worker, payload) {
|
|
||||||
var working = false,
|
|
||||||
tasks = [];
|
|
||||||
|
|
||||||
var cargo = {
|
|
||||||
tasks: tasks,
|
|
||||||
payload: payload,
|
|
||||||
saturated: null,
|
|
||||||
empty: null,
|
|
||||||
drain: null,
|
|
||||||
push: function (data, callback) {
|
|
||||||
if(data.constructor !== Array) {
|
|
||||||
data = [data];
|
|
||||||
}
|
|
||||||
_each(data, function(task) {
|
|
||||||
tasks.push({
|
|
||||||
data: task,
|
|
||||||
callback: typeof callback === 'function' ? callback : null
|
|
||||||
});
|
|
||||||
if (cargo.saturated && tasks.length === payload) {
|
|
||||||
cargo.saturated();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
async.setImmediate(cargo.process);
|
|
||||||
},
|
|
||||||
process: function process() {
|
|
||||||
if (working) return;
|
|
||||||
if (tasks.length === 0) {
|
|
||||||
if(cargo.drain) cargo.drain();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var ts = typeof payload === 'number'
|
|
||||||
? tasks.splice(0, payload)
|
|
||||||
: tasks.splice(0);
|
|
||||||
|
|
||||||
var ds = _map(ts, function (task) {
|
|
||||||
return task.data;
|
|
||||||
});
|
|
||||||
|
|
||||||
if(cargo.empty) cargo.empty();
|
|
||||||
working = true;
|
|
||||||
worker(ds, function () {
|
|
||||||
working = false;
|
|
||||||
|
|
||||||
var args = arguments;
|
|
||||||
_each(ts, function (data) {
|
|
||||||
if (data.callback) {
|
|
||||||
data.callback.apply(null, args);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
process();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
length: function () {
|
|
||||||
return tasks.length;
|
|
||||||
},
|
|
||||||
running: function () {
|
|
||||||
return working;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return cargo;
|
|
||||||
};
|
|
||||||
|
|
||||||
var _console_fn = function (name) {
|
|
||||||
return function (fn) {
|
|
||||||
var args = Array.prototype.slice.call(arguments, 1);
|
|
||||||
fn.apply(null, args.concat([function (err) {
|
|
||||||
var args = Array.prototype.slice.call(arguments, 1);
|
|
||||||
if (typeof console !== 'undefined') {
|
|
||||||
if (err) {
|
|
||||||
if (console.error) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (console[name]) {
|
|
||||||
_each(args, function (x) {
|
|
||||||
console[name](x);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}]));
|
|
||||||
};
|
|
||||||
};
|
|
||||||
async.log = _console_fn('log');
|
|
||||||
async.dir = _console_fn('dir');
|
|
||||||
/*async.info = _console_fn('info');
|
|
||||||
async.warn = _console_fn('warn');
|
|
||||||
async.error = _console_fn('error');*/
|
|
||||||
|
|
||||||
async.memoize = function (fn, hasher) {
|
|
||||||
var memo = {};
|
|
||||||
var queues = {};
|
|
||||||
hasher = hasher || function (x) {
|
|
||||||
return x;
|
|
||||||
};
|
|
||||||
var memoized = function () {
|
|
||||||
var args = Array.prototype.slice.call(arguments);
|
|
||||||
var callback = args.pop();
|
|
||||||
var key = hasher.apply(null, args);
|
|
||||||
if (key in memo) {
|
|
||||||
callback.apply(null, memo[key]);
|
|
||||||
}
|
|
||||||
else if (key in queues) {
|
|
||||||
queues[key].push(callback);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
queues[key] = [callback];
|
|
||||||
fn.apply(null, args.concat([function () {
|
|
||||||
memo[key] = arguments;
|
|
||||||
var q = queues[key];
|
|
||||||
delete queues[key];
|
|
||||||
for (var i = 0, l = q.length; i < l; i++) {
|
|
||||||
q[i].apply(null, arguments);
|
|
||||||
}
|
|
||||||
}]));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
memoized.memo = memo;
|
|
||||||
memoized.unmemoized = fn;
|
|
||||||
return memoized;
|
|
||||||
};
|
|
||||||
|
|
||||||
async.unmemoize = function (fn) {
|
|
||||||
return function () {
|
|
||||||
return (fn.unmemoized || fn).apply(null, arguments);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
async.times = function (count, iterator, callback) {
|
|
||||||
var counter = [];
|
|
||||||
for (var i = 0; i < count; i++) {
|
|
||||||
counter.push(i);
|
|
||||||
}
|
|
||||||
return async.map(counter, iterator, callback);
|
|
||||||
};
|
|
||||||
|
|
||||||
async.timesSeries = function (count, iterator, callback) {
|
|
||||||
var counter = [];
|
|
||||||
for (var i = 0; i < count; i++) {
|
|
||||||
counter.push(i);
|
|
||||||
}
|
|
||||||
return async.mapSeries(counter, iterator, callback);
|
|
||||||
};
|
|
||||||
|
|
||||||
async.compose = function (/* functions... */) {
|
|
||||||
var fns = Array.prototype.reverse.call(arguments);
|
|
||||||
return function () {
|
|
||||||
var that = this;
|
|
||||||
var args = Array.prototype.slice.call(arguments);
|
|
||||||
var callback = args.pop();
|
|
||||||
async.reduce(fns, args, function (newargs, fn, cb) {
|
|
||||||
fn.apply(that, newargs.concat([function () {
|
|
||||||
var err = arguments[0];
|
|
||||||
var nextargs = Array.prototype.slice.call(arguments, 1);
|
|
||||||
cb(err, nextargs);
|
|
||||||
}]))
|
|
||||||
},
|
|
||||||
function (err, results) {
|
|
||||||
callback.apply(that, [err].concat(results));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
var _applyEach = function (eachfn, fns /*args...*/) {
|
|
||||||
var go = function () {
|
|
||||||
var that = this;
|
|
||||||
var args = Array.prototype.slice.call(arguments);
|
|
||||||
var callback = args.pop();
|
|
||||||
return eachfn(fns, function (fn, cb) {
|
|
||||||
fn.apply(that, args.concat([cb]));
|
|
||||||
},
|
|
||||||
callback);
|
|
||||||
};
|
|
||||||
if (arguments.length > 2) {
|
|
||||||
var args = Array.prototype.slice.call(arguments, 2);
|
|
||||||
return go.apply(this, args);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return go;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
async.applyEach = doParallel(_applyEach);
|
|
||||||
async.applyEachSeries = doSeries(_applyEach);
|
|
||||||
|
|
||||||
async.forever = function (fn, callback) {
|
|
||||||
function next(err) {
|
|
||||||
if (err) {
|
|
||||||
if (callback) {
|
|
||||||
return callback(err);
|
|
||||||
}
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
fn(next);
|
|
||||||
}
|
|
||||||
next();
|
|
||||||
};
|
|
||||||
|
|
||||||
// AMD / RequireJS
|
|
||||||
if (typeof define !== 'undefined' && define.amd) {
|
|
||||||
define([], function () {
|
|
||||||
return async;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// Node.js
|
|
||||||
else if (typeof module !== 'undefined' && module.exports) {
|
|
||||||
module.exports = async;
|
|
||||||
}
|
|
||||||
// included directly via <script> tag
|
|
||||||
else {
|
|
||||||
root.async = async;
|
|
||||||
}
|
|
||||||
|
|
||||||
}());
|
|
@ -1,60 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "async",
|
|
||||||
"description": "Higher-order functions and common patterns for asynchronous code",
|
|
||||||
"main": "./lib/async",
|
|
||||||
"author": {
|
|
||||||
"name": "Caolan McMahon"
|
|
||||||
},
|
|
||||||
"version": "0.2.10",
|
|
||||||
"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"
|
|
||||||
},
|
|
||||||
"_id": "async@0.2.10",
|
|
||||||
"dist": {
|
|
||||||
"shasum": "b6bbe0b0674b9d719708ca38de8c237cb526c3d1",
|
|
||||||
"tarball": "http://registry.npmjs.org/async/-/async-0.2.10.tgz"
|
|
||||||
},
|
|
||||||
"_from": "async@0.2.x",
|
|
||||||
"_npmVersion": "1.3.2",
|
|
||||||
"_npmUser": {
|
|
||||||
"name": "caolan",
|
|
||||||
"email": "caolan.mcmahon@gmail.com"
|
|
||||||
},
|
|
||||||
"maintainers": [
|
|
||||||
{
|
|
||||||
"name": "caolan",
|
|
||||||
"email": "caolan@caolanmcmahon.com"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"directories": {},
|
|
||||||
"_shasum": "b6bbe0b0674b9d719708ca38de8c237cb526c3d1",
|
|
||||||
"_resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz",
|
|
||||||
"readme": "ERROR: No README data found!",
|
|
||||||
"homepage": "https://github.com/caolan/async"
|
|
||||||
}
|
|
@ -1,4 +0,0 @@
|
|||||||
language: node_js
|
|
||||||
node_js:
|
|
||||||
- 0.4
|
|
||||||
- 0.6
|
|
@ -1,18 +0,0 @@
|
|||||||
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.
|
|
@ -1,11 +0,0 @@
|
|||||||
var equal = require('../');
|
|
||||||
console.dir([
|
|
||||||
equal(
|
|
||||||
{ a : [ 2, 3 ], b : [ 4 ] },
|
|
||||||
{ a : [ 2, 3 ], b : [ 4 ] }
|
|
||||||
),
|
|
||||||
equal(
|
|
||||||
{ x : 5, y : [6] },
|
|
||||||
{ x : 5, y : 6 }
|
|
||||||
)
|
|
||||||
]);
|
|
@ -1,94 +0,0 @@
|
|||||||
var pSlice = Array.prototype.slice;
|
|
||||||
var objectKeys = require('./lib/keys.js');
|
|
||||||
var isArguments = require('./lib/is_arguments.js');
|
|
||||||
|
|
||||||
var deepEqual = module.exports = function (actual, expected, opts) {
|
|
||||||
if (!opts) opts = {};
|
|
||||||
// 7.1. All identical values are equivalent, as determined by ===.
|
|
||||||
if (actual === expected) {
|
|
||||||
return true;
|
|
||||||
|
|
||||||
} else if (actual instanceof Date && expected instanceof Date) {
|
|
||||||
return actual.getTime() === expected.getTime();
|
|
||||||
|
|
||||||
// 7.3. Other pairs that do not both pass typeof value == 'object',
|
|
||||||
// equivalence is determined by ==.
|
|
||||||
} else if (typeof actual != 'object' && typeof expected != 'object') {
|
|
||||||
return opts.strict ? actual === expected : actual == expected;
|
|
||||||
|
|
||||||
// 7.4. For all other Object pairs, including Array objects, equivalence is
|
|
||||||
// determined by having the same number of owned properties (as verified
|
|
||||||
// with Object.prototype.hasOwnProperty.call), the same set of keys
|
|
||||||
// (although not necessarily the same order), equivalent values for every
|
|
||||||
// corresponding key, and an identical 'prototype' property. Note: this
|
|
||||||
// accounts for both named and indexed properties on Arrays.
|
|
||||||
} else {
|
|
||||||
return objEquiv(actual, expected, opts);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function isUndefinedOrNull(value) {
|
|
||||||
return value === null || value === undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
function isBuffer (x) {
|
|
||||||
if (!x || typeof x !== 'object' || typeof x.length !== 'number') return false;
|
|
||||||
if (typeof x.copy !== 'function' || typeof x.slice !== 'function') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (x.length > 0 && typeof x[0] !== 'number') return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function objEquiv(a, b, opts) {
|
|
||||||
var i, key;
|
|
||||||
if (isUndefinedOrNull(a) || isUndefinedOrNull(b))
|
|
||||||
return false;
|
|
||||||
// an identical 'prototype' property.
|
|
||||||
if (a.prototype !== b.prototype) return false;
|
|
||||||
//~~~I've managed to break Object.keys through screwy arguments passing.
|
|
||||||
// Converting to array solves the problem.
|
|
||||||
if (isArguments(a)) {
|
|
||||||
if (!isArguments(b)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
a = pSlice.call(a);
|
|
||||||
b = pSlice.call(b);
|
|
||||||
return deepEqual(a, b, opts);
|
|
||||||
}
|
|
||||||
if (isBuffer(a)) {
|
|
||||||
if (!isBuffer(b)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (a.length !== b.length) return false;
|
|
||||||
for (i = 0; i < a.length; i++) {
|
|
||||||
if (a[i] !== b[i]) return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
var ka = objectKeys(a),
|
|
||||||
kb = objectKeys(b);
|
|
||||||
} catch (e) {//happens when one is a string literal and the other isn't
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// having the same number of owned properties (keys incorporates
|
|
||||||
// hasOwnProperty)
|
|
||||||
if (ka.length != kb.length)
|
|
||||||
return false;
|
|
||||||
//the same set of keys (although not necessarily the same order),
|
|
||||||
ka.sort();
|
|
||||||
kb.sort();
|
|
||||||
//~~~cheap key test
|
|
||||||
for (i = ka.length - 1; i >= 0; i--) {
|
|
||||||
if (ka[i] != kb[i])
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
//equivalent values for every corresponding key, and
|
|
||||||
//~~~possibly expensive deep test
|
|
||||||
for (i = ka.length - 1; i >= 0; i--) {
|
|
||||||
key = ka[i];
|
|
||||||
if (!deepEqual(a[key], b[key], opts)) return false;
|
|
||||||
}
|
|
||||||
return typeof a === typeof b;
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
var supportsArgumentsClass = (function(){
|
|
||||||
return Object.prototype.toString.call(arguments)
|
|
||||||
})() == '[object Arguments]';
|
|
||||||
|
|
||||||
exports = module.exports = supportsArgumentsClass ? supported : unsupported;
|
|
||||||
|
|
||||||
exports.supported = supported;
|
|
||||||
function supported(object) {
|
|
||||||
return Object.prototype.toString.call(object) == '[object Arguments]';
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.unsupported = unsupported;
|
|
||||||
function unsupported(object){
|
|
||||||
return object &&
|
|
||||||
typeof object == 'object' &&
|
|
||||||
typeof object.length == 'number' &&
|
|
||||||
Object.prototype.hasOwnProperty.call(object, 'callee') &&
|
|
||||||
!Object.prototype.propertyIsEnumerable.call(object, 'callee') ||
|
|
||||||
false;
|
|
||||||
};
|
|
@ -1,9 +0,0 @@
|
|||||||
exports = module.exports = typeof Object.keys === 'function'
|
|
||||||
? Object.keys : shim;
|
|
||||||
|
|
||||||
exports.shim = shim;
|
|
||||||
function shim (obj) {
|
|
||||||
var keys = [];
|
|
||||||
for (var key in obj) keys.push(key);
|
|
||||||
return keys;
|
|
||||||
}
|
|
@ -1,84 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "deep-equal",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"description": "node's assert.deepEqual algorithm",
|
|
||||||
"main": "index.js",
|
|
||||||
"directories": {
|
|
||||||
"lib": ".",
|
|
||||||
"example": "example",
|
|
||||||
"test": "test"
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"test": "tape test/*.js"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"tape": "^3.5.0"
|
|
||||||
},
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "http://github.com/substack/node-deep-equal.git"
|
|
||||||
},
|
|
||||||
"keywords": [
|
|
||||||
"equality",
|
|
||||||
"equal",
|
|
||||||
"compare"
|
|
||||||
],
|
|
||||||
"author": {
|
|
||||||
"name": "James Halliday",
|
|
||||||
"email": "mail@substack.net",
|
|
||||||
"url": "http://substack.net"
|
|
||||||
},
|
|
||||||
"license": "MIT",
|
|
||||||
"testling": {
|
|
||||||
"files": "test/*.js",
|
|
||||||
"browsers": {
|
|
||||||
"ie": [
|
|
||||||
6,
|
|
||||||
7,
|
|
||||||
8,
|
|
||||||
9
|
|
||||||
],
|
|
||||||
"ff": [
|
|
||||||
3.5,
|
|
||||||
10,
|
|
||||||
15
|
|
||||||
],
|
|
||||||
"chrome": [
|
|
||||||
10,
|
|
||||||
22
|
|
||||||
],
|
|
||||||
"safari": [
|
|
||||||
5.1
|
|
||||||
],
|
|
||||||
"opera": [
|
|
||||||
12
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"gitHead": "39c740ebdafed9443912a4ef1493b18693934daf",
|
|
||||||
"bugs": {
|
|
||||||
"url": "https://github.com/substack/node-deep-equal/issues"
|
|
||||||
},
|
|
||||||
"homepage": "https://github.com/substack/node-deep-equal",
|
|
||||||
"_id": "deep-equal@1.0.0",
|
|
||||||
"_shasum": "d4564f07d2f0ab3e46110bec16592abd7dc2e326",
|
|
||||||
"_from": "deep-equal@*",
|
|
||||||
"_npmVersion": "2.3.0",
|
|
||||||
"_nodeVersion": "0.10.35",
|
|
||||||
"_npmUser": {
|
|
||||||
"name": "substack",
|
|
||||||
"email": "mail@substack.net"
|
|
||||||
},
|
|
||||||
"maintainers": [
|
|
||||||
{
|
|
||||||
"name": "substack",
|
|
||||||
"email": "mail@substack.net"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"dist": {
|
|
||||||
"shasum": "d4564f07d2f0ab3e46110bec16592abd7dc2e326",
|
|
||||||
"tarball": "http://registry.npmjs.org/deep-equal/-/deep-equal-1.0.0.tgz"
|
|
||||||
},
|
|
||||||
"_resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.0.tgz",
|
|
||||||
"readme": "ERROR: No README data found!"
|
|
||||||
}
|
|
@ -1,61 +0,0 @@
|
|||||||
# deep-equal
|
|
||||||
|
|
||||||
Node's `assert.deepEqual() algorithm` as a standalone module.
|
|
||||||
|
|
||||||
This module is around [5 times faster](https://gist.github.com/2790507)
|
|
||||||
than wrapping `assert.deepEqual()` in a `try/catch`.
|
|
||||||
|
|
||||||
[](https://ci.testling.com/substack/node-deep-equal)
|
|
||||||
|
|
||||||
[](https://travis-ci.org/substack/node-deep-equal)
|
|
||||||
|
|
||||||
# example
|
|
||||||
|
|
||||||
``` js
|
|
||||||
var equal = require('deep-equal');
|
|
||||||
console.dir([
|
|
||||||
equal(
|
|
||||||
{ a : [ 2, 3 ], b : [ 4 ] },
|
|
||||||
{ a : [ 2, 3 ], b : [ 4 ] }
|
|
||||||
),
|
|
||||||
equal(
|
|
||||||
{ x : 5, y : [6] },
|
|
||||||
{ x : 5, y : 6 }
|
|
||||||
)
|
|
||||||
]);
|
|
||||||
```
|
|
||||||
|
|
||||||
# methods
|
|
||||||
|
|
||||||
``` js
|
|
||||||
var deepEqual = require('deep-equal')
|
|
||||||
```
|
|
||||||
|
|
||||||
## deepEqual(a, b, opts)
|
|
||||||
|
|
||||||
Compare objects `a` and `b`, returning whether they are equal according to a
|
|
||||||
recursive equality algorithm.
|
|
||||||
|
|
||||||
If `opts.strict` is `true`, use strict equality (`===`) to compare leaf nodes.
|
|
||||||
The default is to use coercive equality (`==`) because that's how
|
|
||||||
`assert.deepEqual()` works by default.
|
|
||||||
|
|
||||||
# install
|
|
||||||
|
|
||||||
With [npm](http://npmjs.org) do:
|
|
||||||
|
|
||||||
```
|
|
||||||
npm install deep-equal
|
|
||||||
```
|
|
||||||
|
|
||||||
# test
|
|
||||||
|
|
||||||
With [npm](http://npmjs.org) do:
|
|
||||||
|
|
||||||
```
|
|
||||||
npm test
|
|
||||||
```
|
|
||||||
|
|
||||||
# license
|
|
||||||
|
|
||||||
MIT. Derived largely from node's assert module.
|
|
@ -1,89 +0,0 @@
|
|||||||
var test = require('tape');
|
|
||||||
var equal = require('../');
|
|
||||||
var isArguments = require('../lib/is_arguments.js');
|
|
||||||
var objectKeys = require('../lib/keys.js');
|
|
||||||
|
|
||||||
test('equal', function (t) {
|
|
||||||
t.ok(equal(
|
|
||||||
{ a : [ 2, 3 ], b : [ 4 ] },
|
|
||||||
{ a : [ 2, 3 ], b : [ 4 ] }
|
|
||||||
));
|
|
||||||
t.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('not equal', function (t) {
|
|
||||||
t.notOk(equal(
|
|
||||||
{ x : 5, y : [6] },
|
|
||||||
{ x : 5, y : 6 }
|
|
||||||
));
|
|
||||||
t.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('nested nulls', function (t) {
|
|
||||||
t.ok(equal([ null, null, null ], [ null, null, null ]));
|
|
||||||
t.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('strict equal', function (t) {
|
|
||||||
t.notOk(equal(
|
|
||||||
[ { a: 3 }, { b: 4 } ],
|
|
||||||
[ { a: '3' }, { b: '4' } ],
|
|
||||||
{ strict: true }
|
|
||||||
));
|
|
||||||
t.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('non-objects', function (t) {
|
|
||||||
t.ok(equal(3, 3));
|
|
||||||
t.ok(equal('beep', 'beep'));
|
|
||||||
t.ok(equal('3', 3));
|
|
||||||
t.notOk(equal('3', 3, { strict: true }));
|
|
||||||
t.notOk(equal('3', [3]));
|
|
||||||
t.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('arguments class', function (t) {
|
|
||||||
t.ok(equal(
|
|
||||||
(function(){return arguments})(1,2,3),
|
|
||||||
(function(){return arguments})(1,2,3),
|
|
||||||
"compares arguments"
|
|
||||||
));
|
|
||||||
t.notOk(equal(
|
|
||||||
(function(){return arguments})(1,2,3),
|
|
||||||
[1,2,3],
|
|
||||||
"differenciates array and arguments"
|
|
||||||
));
|
|
||||||
t.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('test the arguments shim', function (t) {
|
|
||||||
t.ok(isArguments.supported((function(){return arguments})()));
|
|
||||||
t.notOk(isArguments.supported([1,2,3]));
|
|
||||||
|
|
||||||
t.ok(isArguments.unsupported((function(){return arguments})()));
|
|
||||||
t.notOk(isArguments.unsupported([1,2,3]));
|
|
||||||
|
|
||||||
t.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('test the keys shim', function (t) {
|
|
||||||
t.deepEqual(objectKeys.shim({ a: 1, b : 2 }), [ 'a', 'b' ]);
|
|
||||||
t.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('dates', function (t) {
|
|
||||||
var d0 = new Date(1387585278000);
|
|
||||||
var d1 = new Date('Fri Dec 20 2013 16:21:18 GMT-0800 (PST)');
|
|
||||||
t.ok(equal(d0, d1));
|
|
||||||
t.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('buffers', function (t) {
|
|
||||||
t.ok(equal(Buffer('xyz'), Buffer('xyz')));
|
|
||||||
t.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('booleans and arrays', function (t) {
|
|
||||||
t.notOk(equal(true, []));
|
|
||||||
t.end();
|
|
||||||
})
|
|
@ -1,3 +0,0 @@
|
|||||||
node_modules
|
|
||||||
npm-debug.log
|
|
||||||
*.swp
|
|
@ -1,9 +0,0 @@
|
|||||||
language: node_js
|
|
||||||
node_js:
|
|
||||||
- 0.4
|
|
||||||
- 0.6
|
|
||||||
- 0.7
|
|
||||||
notifications:
|
|
||||||
irc: "irc.freenode.net#pksunkara"
|
|
||||||
email:
|
|
||||||
on_success: never
|
|
@ -1,18 +0,0 @@
|
|||||||
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.
|
|
@ -1,174 +0,0 @@
|
|||||||
# inflect
|
|
||||||
|
|
||||||
customizable inflections for nodejs
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm install i
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
Require the module before using
|
|
||||||
|
|
||||||
```js
|
|
||||||
var inflect = require('i')();
|
|
||||||
```
|
|
||||||
|
|
||||||
All the below api functions can be called directly on a string
|
|
||||||
|
|
||||||
```js
|
|
||||||
inflect.titleize('messages to store') // === 'Messages To Store'
|
|
||||||
'messages to store'.titleize // === 'Messages To Store'
|
|
||||||
```
|
|
||||||
|
|
||||||
only if `true` is passed while initiating
|
|
||||||
|
|
||||||
```js
|
|
||||||
var inflect = require('i')(true);
|
|
||||||
```
|
|
||||||
|
|
||||||
### Pluralize
|
|
||||||
|
|
||||||
```js
|
|
||||||
inflect.pluralize('person'); // === 'people'
|
|
||||||
inflect.pluralize('octopus'); // === 'octopi'
|
|
||||||
inflect.pluralize('Hat'); // === 'Hats'
|
|
||||||
```
|
|
||||||
|
|
||||||
### Singularize
|
|
||||||
|
|
||||||
```js
|
|
||||||
inflect.singularize('people'); // === 'person'
|
|
||||||
inflect.singularize('octopi'); // === 'octopus'
|
|
||||||
inflect.singularize('Hats'); // === 'Hat'
|
|
||||||
```
|
|
||||||
|
|
||||||
### Camelize
|
|
||||||
|
|
||||||
```js
|
|
||||||
inflect.camelize('message_properties'); // === 'MessageProperties'
|
|
||||||
inflect.camelize('message_properties', false); // === 'messageProperties'
|
|
||||||
```
|
|
||||||
|
|
||||||
### Underscore
|
|
||||||
|
|
||||||
```js
|
|
||||||
inflect.underscore('MessageProperties'); // === 'message_properties'
|
|
||||||
inflect.underscore('messageProperties'); // === 'message_properties'
|
|
||||||
```
|
|
||||||
|
|
||||||
### Humanize
|
|
||||||
|
|
||||||
```js
|
|
||||||
inflect.humanize('message_id'); // === 'Message'
|
|
||||||
```
|
|
||||||
|
|
||||||
### Dasherize
|
|
||||||
|
|
||||||
```js
|
|
||||||
inflect.dasherize('message_properties'); // === 'message-properties'
|
|
||||||
inflect.dasherize('Message Properties'); // === 'Message Properties'
|
|
||||||
```
|
|
||||||
|
|
||||||
### Titleize
|
|
||||||
|
|
||||||
```js
|
|
||||||
inflect.titleize('message_properties'); // === 'Message Properties'
|
|
||||||
inflect.titleize('message properties to keep'); // === 'Message Properties to Keep'
|
|
||||||
```
|
|
||||||
|
|
||||||
### Demodulize
|
|
||||||
|
|
||||||
```js
|
|
||||||
inflect.demodulize('Message.Bus.Properties'); // === 'Properties'
|
|
||||||
```
|
|
||||||
|
|
||||||
### Tableize
|
|
||||||
|
|
||||||
```js
|
|
||||||
inflect.tableize('MessageBusProperty'); // === 'message_bus_properties'
|
|
||||||
```
|
|
||||||
|
|
||||||
### Classify
|
|
||||||
|
|
||||||
```js
|
|
||||||
inflect.classify('message_bus_properties'); // === 'MessageBusProperty'
|
|
||||||
```
|
|
||||||
|
|
||||||
### Foreign key
|
|
||||||
|
|
||||||
```js
|
|
||||||
inflect.foreign_key('MessageBusProperty'); // === 'message_bus_property_id'
|
|
||||||
inflect.foreign_key('MessageBusProperty', false); // === 'message_bus_propertyid'
|
|
||||||
```
|
|
||||||
|
|
||||||
### Ordinalize
|
|
||||||
|
|
||||||
```js
|
|
||||||
inflect.ordinalize( '1' ); // === '1st'
|
|
||||||
```
|
|
||||||
|
|
||||||
## Custom rules for inflection
|
|
||||||
|
|
||||||
### Custom plural
|
|
||||||
|
|
||||||
We can use regexp in any of these custom rules
|
|
||||||
|
|
||||||
```js
|
|
||||||
inflect.inflections.plural('person', 'guys');
|
|
||||||
inflect.pluralize('person'); // === 'guys'
|
|
||||||
inflect.singularize('guys'); // === 'guy'
|
|
||||||
```
|
|
||||||
|
|
||||||
### Custom singular
|
|
||||||
|
|
||||||
```js
|
|
||||||
inflect.inflections.singular('guys', 'person')
|
|
||||||
inflect.singularize('guys'); // === 'person'
|
|
||||||
inflect.pluralize('person'); // === 'people'
|
|
||||||
```
|
|
||||||
|
|
||||||
### Custom irregular
|
|
||||||
|
|
||||||
```js
|
|
||||||
inflect.inflections.irregular('person', 'guys')
|
|
||||||
inflect.pluralize('person'); // === 'guys'
|
|
||||||
inflect.singularize('guys'); // === 'person'
|
|
||||||
```
|
|
||||||
|
|
||||||
### Custom human
|
|
||||||
|
|
||||||
```js
|
|
||||||
inflect.inflections.human(/^(.*)_cnt$/i, '$1_count');
|
|
||||||
inflect.inflections.humanize('jargon_cnt'); // === 'Jargon count'
|
|
||||||
```
|
|
||||||
|
|
||||||
### Custom uncountable
|
|
||||||
|
|
||||||
```js
|
|
||||||
inflect.inflections.uncountable('oil')
|
|
||||||
inflect.pluralize('oil'); // === 'oil'
|
|
||||||
inflect.singularize('oil'); // === 'oil'
|
|
||||||
```
|
|
||||||
|
|
||||||
## Contributors
|
|
||||||
Here is a list of [Contributors](http://github.com/pksunkara/inflect/contributors)
|
|
||||||
|
|
||||||
### TODO
|
|
||||||
|
|
||||||
- More obscure test cases
|
|
||||||
|
|
||||||
__I accept pull requests and guarantee a reply back within a day__
|
|
||||||
|
|
||||||
## License
|
|
||||||
MIT/X11
|
|
||||||
|
|
||||||
## Bug Reports
|
|
||||||
Report [here](http://github.com/pksunkara/inflect/issues). __Guaranteed reply within a day__.
|
|
||||||
|
|
||||||
## Contact
|
|
||||||
Pavan Kumar Sunkara (pavan.sss1991@gmail.com)
|
|
||||||
|
|
||||||
Follow me on [github](https://github.com/users/follow?target=pksunkara), [twitter](http://twitter.com/pksunkara)
|
|
@ -1,63 +0,0 @@
|
|||||||
// Default inflections
|
|
||||||
module.exports = function (inflect) {
|
|
||||||
|
|
||||||
inflect.plural(/$/, 's');
|
|
||||||
inflect.plural(/s$/i, 's');
|
|
||||||
inflect.plural(/(ax|test)is$/i, '$1es');
|
|
||||||
inflect.plural(/(octop|vir)us$/i, '$1i');
|
|
||||||
inflect.plural(/(octop|vir)i$/i, '$1i');
|
|
||||||
inflect.plural(/(alias|status)$/i, '$1es');
|
|
||||||
inflect.plural(/(bu)s$/i, '$1ses');
|
|
||||||
inflect.plural(/(buffal|tomat)o$/i, '$1oes');
|
|
||||||
inflect.plural(/([ti])um$/i, '$1a');
|
|
||||||
inflect.plural(/([ti])a$/i, '$1a');
|
|
||||||
inflect.plural(/sis$/i, 'ses');
|
|
||||||
inflect.plural(/(?:([^f])fe|([lr])f)$/i, '$1ves');
|
|
||||||
inflect.plural(/(hive)$/i, '$1s');
|
|
||||||
inflect.plural(/([^aeiouy]|qu)y$/i, '$1ies');
|
|
||||||
inflect.plural(/(x|ch|ss|sh)$/i, '$1es');
|
|
||||||
inflect.plural(/(matr|vert|ind)(?:ix|ex)$/i, '$1ices');
|
|
||||||
inflect.plural(/([m|l])ouse$/i, '$1ice');
|
|
||||||
inflect.plural(/([m|l])ice$/i, '$1ice');
|
|
||||||
inflect.plural(/^(ox)$/i, '$1en');
|
|
||||||
inflect.plural(/^(oxen)$/i, '$1');
|
|
||||||
inflect.plural(/(quiz)$/i, '$1zes');
|
|
||||||
|
|
||||||
|
|
||||||
inflect.singular(/s$/i, '');
|
|
||||||
inflect.singular(/(n)ews$/i, '$1ews');
|
|
||||||
inflect.singular(/([ti])a$/i, '$1um');
|
|
||||||
inflect.singular(/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i, '$1sis');
|
|
||||||
inflect.singular(/(^analy)ses$/i, '$1sis');
|
|
||||||
inflect.singular(/([^f])ves$/i, '$1fe');
|
|
||||||
inflect.singular(/(hive)s$/i, '$1');
|
|
||||||
inflect.singular(/(tive)s$/i, '$1');
|
|
||||||
inflect.singular(/([lr])ves$/i, '$1f');
|
|
||||||
inflect.singular(/([^aeiouy]|qu)ies$/i, '$1y');
|
|
||||||
inflect.singular(/(s)eries$/i, '$1eries');
|
|
||||||
inflect.singular(/(m)ovies$/i, '$1ovie');
|
|
||||||
inflect.singular(/(x|ch|ss|sh)es$/i, '$1');
|
|
||||||
inflect.singular(/([m|l])ice$/i, '$1ouse');
|
|
||||||
inflect.singular(/(bus)es$/i, '$1');
|
|
||||||
inflect.singular(/(o)es$/i, '$1');
|
|
||||||
inflect.singular(/(shoe)s$/i, '$1');
|
|
||||||
inflect.singular(/(cris|ax|test)es$/i, '$1is');
|
|
||||||
inflect.singular(/(octop|vir)i$/i, '$1us');
|
|
||||||
inflect.singular(/(alias|status)es$/i, '$1');
|
|
||||||
inflect.singular(/^(ox)en/i, '$1');
|
|
||||||
inflect.singular(/(vert|ind)ices$/i, '$1ex');
|
|
||||||
inflect.singular(/(matr)ices$/i, '$1ix');
|
|
||||||
inflect.singular(/(quiz)zes$/i, '$1');
|
|
||||||
inflect.singular(/(database)s$/i, '$1');
|
|
||||||
|
|
||||||
inflect.irregular('child', 'children');
|
|
||||||
inflect.irregular('person', 'people');
|
|
||||||
inflect.irregular('man', 'men');
|
|
||||||
inflect.irregular('child', 'children');
|
|
||||||
inflect.irregular('sex', 'sexes');
|
|
||||||
inflect.irregular('move', 'moves');
|
|
||||||
inflect.irregular('cow', 'kine');
|
|
||||||
inflect.irregular('zombie', 'zombies');
|
|
||||||
|
|
||||||
inflect.uncountable(['equipment', 'information', 'rice', 'money', 'species', 'series', 'fish', 'sheep', 'jeans']);
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user