Commit a02e1b72 by Sebastián Katzer

Update ios platform

parent 51f498a9
......@@ -36,8 +36,8 @@ module.exports = [
]
},
{
"file": "plugins/org.apache.cordova.device/www/device.js",
"id": "org.apache.cordova.device.device",
"file": "plugins/cordova-plugin-device/www/device.js",
"id": "cordova-plugin-device.device",
"clobbers": [
"device"
]
......@@ -49,8 +49,8 @@ module.exports.metadata =
"android.support.v4": "21.0.1",
"de.appplant.cordova.common.registerusernotificationsettings": "1.0.1",
"nl.x-services.plugins.toast": "2.0.4",
"de.appplant.cordova.plugin.local-notification": "0.8.2dev",
"org.apache.cordova.device": "0.3.0"
"de.appplant.cordova.plugin.local-notification": "0.8.2-dev",
"cordova-plugin-device": "1.0.1"
}
// BOTTOM OF METADATA
});
\ No newline at end of file
cordova.define("org.apache.cordova.device.device", function(require, exports, module) { /*
cordova.define("cordova-plugin-device.device", function(require, exports, module) { /*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
......
......@@ -4,12 +4,6 @@
<feature name="Toast">
<param name="android-package" value="nl.xservices.plugins.Toast" />
</feature>
<feature name="Device">
<param name="android-package" value="org.apache.cordova.device.Device" />
</feature>
<feature name="LocalNotification">
<param name="android-package" value="de.appplant.cordova.plugin.localnotification.LocalNotification" />
</feature>
<name>NotificationExample</name>
<description>
A sample Apache Cordova application that responds to the deviceready event.
......@@ -19,4 +13,10 @@
</author>
<content src="index.html" />
<access origin="*" />
<feature name="Device">
<param name="android-package" value="org.apache.cordova.device.Device" />
</feature>
<feature name="LocalNotification">
<param name="android-package" value="de.appplant.cordova.plugin.localnotification.LocalNotification" />
</feature>
</widget>
......@@ -55,6 +55,8 @@
#define __CORDOVA_3_6_0 30600
#define __CORDOVA_3_7_0 30700
#define __CORDOVA_3_8_0 30800
#define __CORDOVA_3_9_0 30900
#define __CORDOVA_3_9_1 30901
#define __CORDOVA_NA 99999 /* not available */
/*
......@@ -65,7 +67,7 @@
#endif
*/
#ifndef CORDOVA_VERSION_MIN_REQUIRED
#define CORDOVA_VERSION_MIN_REQUIRED __CORDOVA_3_8_0
#define CORDOVA_VERSION_MIN_REQUIRED __CORDOVA_3_9_1
#endif
/*
......
......@@ -143,7 +143,7 @@
- (void)evalJs:(NSString*)js scheduledOnRunLoop:(BOOL)scheduledOnRunLoop
{
js = [NSString stringWithFormat:@"cordova.require('cordova/exec').nativeEvalAndFetch(function(){%@})", js];
js = [NSString stringWithFormat:@"try{cordova.require('cordova/exec').nativeEvalAndFetch(function(){%@})}catch(e){console.log('exeption nativeEvalAndFetch : '+e);};", js];
if (scheduledOnRunLoop) {
[self evalJsHelper:js];
} else {
......
......@@ -601,13 +601,22 @@
- (NSString*)userAgent
{
if (_userAgent == nil) {
if (_userAgent != nil) {
return _userAgent;
}
NSString* localBaseUserAgent;
if (self.baseUserAgent != nil) {
localBaseUserAgent = self.baseUserAgent;
} else if ([self settingForKey:@"OverrideUserAgent"] != nil) {
localBaseUserAgent = [self settingForKey:@"OverrideUserAgent"];
} else {
localBaseUserAgent = [CDVUserAgentUtil originalUserAgent];
}
NSString* appendUserAgent = [self settingForKey:@"AppendUserAgent"];
if (appendUserAgent) {
_userAgent = [NSString stringWithFormat:@"%@ %@", localBaseUserAgent, appendUserAgent];
} else {
// Use our address as a unique number to append to the User-Agent.
_userAgent = [NSString stringWithFormat:@"%@ (%lld)", localBaseUserAgent, (long long)self];
}
......@@ -980,6 +989,13 @@
{
// NSLog(@"%@",@"applicationWillEnterForeground");
[self.commandDelegate evalJs:@"cordova.fireDocumentEvent('resume');"];
/** Clipboard fix **/
UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
NSString *string = pasteboard.string;
if (string) {
[pasteboard setValue:string forPasteboardType:@"public.text"];
}
}
// This method is called to let your application know that it moved from the inactive to active state.
......
......@@ -197,7 +197,7 @@ static NSString *stripFragment(NSString* url)
{
NSString* scheme = [[request URL] scheme];
if ([scheme isEqualToString:@"mailto"] || [scheme isEqualToString:@"tel"]) {
if ([scheme isEqualToString:@"mailto"] || [scheme isEqualToString:@"tel"] || [scheme isEqualToString:@"sms"]) {
return YES;
}
......@@ -251,10 +251,10 @@ static NSString *stripFragment(NSString* url)
default:
{
_loadCount = 0;
_state = STATE_WAITING_FOR_LOAD_START;
NSString* description = [NSString stringWithFormat:@"CDVWebViewDelegate: Navigation started when state=%ld", (long)_state];
NSLog(@"%@", description);
_loadCount = 0;
_state = STATE_WAITING_FOR_LOAD_START;
if ([_delegate respondsToSelector:@selector(webView:didFailLoadWithError:)]) {
NSDictionary* errorDictionary = @{NSLocalizedDescriptionKey : description};
NSError* error = [[NSError alloc] initWithDomain:@"CDVWebViewDelegate" code:1 userInfo:errorDictionary];
......
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0630"
LastUpgradeVersion = "0640"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
......
// Platform: ios
// fc4db9145934bd0053161cbf9ffc0caf83b770c6
// 2c29e187e4206a6a77fba940ef6f77aef5c7eb8c
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
......@@ -19,7 +19,7 @@
under the License.
*/
;(function() {
var PLATFORM_VERSION_BUILD_LABEL = '3.8.0';
var PLATFORM_VERSION_BUILD_LABEL = '3.9.1';
// file: src/scripts/require.js
/*jshint -W079 */
......@@ -101,10 +101,15 @@ if (typeof module === "object" && typeof require === "function") {
// file: src/cordova.js
define("cordova", function(require, exports, module) {
if(window.cordova){
throw new Error("cordova already defined");
}
var channel = require('cordova/channel');
var platform = require('cordova/platform');
/**
* Intercept calls to addEventListener + removeEventListener and handle deviceready,
* resume, and pause events.
......@@ -326,7 +331,6 @@ module.exports = cordova;
// file: src/common/argscheck.js
define("cordova/argscheck", function(require, exports, module) {
var exec = require('cordova/exec');
var utils = require('cordova/utils');
var moduleExports = module.exports;
......@@ -811,7 +815,7 @@ module.exports = channel;
});
// file: src/ios/exec.js
// file: /Users/steveng/repo/cordova/cordova-ios/cordova-js-src/exec.js
define("cordova/exec", function(require, exports, module) {
/**
......@@ -1220,6 +1224,7 @@ if (!window.console.warn) {
// Register pause, resume and deviceready channels as events on document.
channel.onPause = cordova.addDocumentEventHandler('pause');
channel.onResume = cordova.addDocumentEventHandler('resume');
channel.onActivated = cordova.addDocumentEventHandler('activated');
channel.onDeviceReady = cordova.addStickyDocumentEventHandler('deviceready');
// Listen for DOMContentLoaded and notify our channel subscribers.
......@@ -1347,6 +1352,7 @@ if (!window.console.warn) {
// Register pause, resume and deviceready channels as events on document.
channel.onPause = cordova.addDocumentEventHandler('pause');
channel.onResume = cordova.addDocumentEventHandler('resume');
channel.onActivated = cordova.addDocumentEventHandler('activated');
channel.onDeviceReady = cordova.addStickyDocumentEventHandler('deviceready');
// Listen for DOMContentLoaded and notify our channel subscribers.
......@@ -1490,7 +1496,7 @@ exports.reset();
});
// file: src/ios/platform.js
// file: /Users/steveng/repo/cordova/cordova-ios/cordova-js-src/platform.js
define("cordova/platform", function(require, exports, module) {
module.exports = {
......@@ -1506,6 +1512,10 @@ module.exports = {
// file: src/common/pluginloader.js
define("cordova/pluginloader", function(require, exports, module) {
/*
NOTE: this file is NOT used when we use the browserify workflow
*/
var modulemapper = require('cordova/modulemapper');
var urlutil = require('cordova/urlutil');
......@@ -1694,15 +1704,14 @@ utils.typeName = function(val) {
/**
* Returns an indication of whether the argument is an array or not
*/
utils.isArray = function(a) {
return utils.typeName(a) == 'Array';
};
utils.isArray = Array.isArray ||
function(a) {return utils.typeName(a) == 'Array';};
/**
* Returns an indication of whether the argument is a Date or not
*/
utils.isDate = function(d) {
return utils.typeName(d) == 'Date';
return (d instanceof Date);
};
/**
......@@ -1736,17 +1745,25 @@ utils.clone = function(obj) {
* Returns a wrapped version of the function
*/
utils.close = function(context, func, params) {
if (typeof params == 'undefined') {
return function() {
return func.apply(context, arguments);
};
} else {
return function() {
return func.apply(context, params);
var args = params || arguments;
return func.apply(context, args);
};
}
};
//------------------------------------------------------------------------------
function UUIDcreatePart(length) {
var uuidpart = "";
for (var i=0; i<length; i++) {
var uuidchar = parseInt((Math.random() * 256), 10).toString(16);
if (uuidchar.length == 1) {
uuidchar = "0" + uuidchar;
}
uuidpart += uuidchar;
}
return uuidpart;
}
/**
* Create a UUID
*/
......@@ -1758,6 +1775,7 @@ utils.createUUID = function() {
UUIDcreatePart(6);
};
/**
* Extends a child object from a parent object using classical inheritance
* pattern.
......@@ -1767,6 +1785,7 @@ utils.extend = (function() {
var F = function() {};
// extend Child from Parent
return function(Child, Parent) {
F.prototype = Parent.prototype;
Child.prototype = new F();
Child.__super__ = Parent.prototype;
......@@ -1786,18 +1805,7 @@ utils.alert = function(msg) {
};
//------------------------------------------------------------------------------
function UUIDcreatePart(length) {
var uuidpart = "";
for (var i=0; i<length; i++) {
var uuidchar = parseInt((Math.random() * 256), 10).toString(16);
if (uuidchar.length == 1) {
uuidchar = "0" + uuidchar;
}
uuidpart += uuidchar;
}
return uuidpart;
}
});
......
......@@ -5,7 +5,7 @@
<key>IDESourceControlProjectFavoriteDictionaryKey</key>
<false/>
<key>IDESourceControlProjectIdentifier</key>
<string>7CCE7CC9-2C07-4A1A-ACE8-4E4BCCE66A22</string>
<string>0B4D9F20-F7BE-4517-A3A6-1D92D25D9238</string>
<key>IDESourceControlProjectName</key>
<string>NotificationExample</string>
<key>IDESourceControlProjectOriginsDictionary</key>
......
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0630"
LastUpgradeVersion = "0640"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
......
......@@ -29,8 +29,6 @@
#import <Cordova/CDVViewController.h>
extern NSString* const UIApplicationRegisterUserNotificationSettings;
@interface AppDelegate : NSObject <UIApplicationDelegate>{}
// invoke string is passed to your app on launch, this is only valid if you
......
......@@ -30,8 +30,6 @@
#import <Cordova/CDVPlugin.h>
NSString* const UIApplicationRegisterUserNotificationSettings = @"UIApplicationRegisterUserNotificationSettings";
@implementation AppDelegate
@synthesize window, viewController;
......@@ -150,18 +148,4 @@ NSString* const UIApplicationRegisterUserNotificationSettings = @"UIApplicationR
[[NSURLCache sharedURLCache] removeAllCachedResponses];
}
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
- (void) application:(UIApplication*)application
didRegisterUserNotificationSettings:(UIUserNotificationSettings*)settings
{
NSNotificationCenter* center = [NSNotificationCenter
defaultCenter];
// re-post (broadcast)
[center postNotificationName:UIApplicationRegisterUserNotificationSettings
object:settings];
}
#endif
@end
......@@ -68,13 +68,6 @@
<string></string>
<key>NSMainNibFile~ipad</key>
<string></string>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UILaunchImages</key>
<array>
<dict>
......
/*
* Copyright (c) 2013-2015 by appPlant UG. All rights reserved.
*
* @APPPLANT_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPPLANT_LICENSE_HEADER_END@
*/
#import "AppDelegate.h"
#import <Availability.h>
extern NSString* const UIApplicationRegisterUserNotificationSettings;
@interface AppDelegate (APPRegisterUserNotificationSettings)
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
// Tells the delegate what types of notifications may be used
- (void) application:(UIApplication*)application
didRegisterUserNotificationSettings:(UIUserNotificationSettings*)settings;
#endif
@end
\ No newline at end of file
/*
* Copyright (c) 2013-2015 by appPlant UG. All rights reserved.
*
* @APPPLANT_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPPLANT_LICENSE_HEADER_END@
*/
#import "AppDelegate+APPRegisterUserNotificationSettings.h"
#import <Availability.h>
NSString* const UIApplicationRegisterUserNotificationSettings = @"UIApplicationRegisterUserNotificationSettings";
@implementation AppDelegate (APPRegisterUserNotificationSettings)
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
/**
* Tells the delegate what types of notifications may be used
* to get the user’s attention.
*/
- (void) application:(UIApplication*)application
didRegisterUserNotificationSettings:(UIUserNotificationSettings*)settings
{
NSNotificationCenter* center = [NSNotificationCenter
defaultCenter];
// re-post (broadcast)
[center postNotificationName:UIApplicationRegisterUserNotificationSettings
object:settings];
}
#endif
@end
\ No newline at end of file
......@@ -21,11 +21,11 @@
* @APPPLANT_LICENSE_HEADER_END@
*/
#import "AppDelegate.h"
#import "APPLocalNotification.h"
#import "APPLocalNotificationOptions.h"
#import "UIApplication+APPLocalNotification.h"
#import "UILocalNotification+APPLocalNotification.h"
#import "AppDelegate+APPRegisterUserNotificationSettings.h"
@interface APPLocalNotification ()
......
......@@ -29,7 +29,7 @@ NSString* const DEFAULT_SOUND = @"res://platform_default";
@interface APPLocalNotificationOptions ()
// The dictionary which contains all notification properties
@property(readwrite, assign) NSDictionary* dict;
@property(nonatomic, retain) NSDictionary* dict;
@end
......
......@@ -22,3 +22,4 @@
//
#include "build.xcconfig"
#include "build-extras.xcconfig"
//
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
//
// Auto-generated config file to override configuration files (build-release/build-debug).
//
......@@ -25,3 +25,5 @@
CODE_SIGN_IDENTITY = iPhone Distribution
CODE_SIGN_IDENTITY[sdk=iphoneos*] = iPhone Distribution
#include "build-extras.xcconfig"
:: Licensed to the Apache Software Foundation (ASF) under one
:: or more contributor license agreements. See the NOTICE file
:: distributed with this work for additional information
:: regarding copyright ownership. The ASF licenses this file
:: to you under the Apache License, Version 2.0 (the
:: "License"); you may not use this file except in compliance
:: with the License. You may obtain a copy of the License at
::
:: http://www.apache.org/licenses/LICENSE-2.0
::
:: Unless required by applicable law or agreed to in writing,
:: software distributed under the License is distributed on an
:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
:: KIND, either express or implied. See the License for the
:: specific language governing permissions and limitations
:: under the License
@ECHO OFF
SET script_path="%~dp0check_reqs"
IF EXIST %script_path% (
node "%script_path%" %*
) ELSE (
ECHO.
ECHO ERROR: Could not find 'check_reqs' script in 'bin' folder, aborting...>&2
EXIT /B 1
)
\ No newline at end of file
......@@ -24,9 +24,11 @@ var Q = require('q'),
path = require('path'),
shell = require('shelljs'),
spawn = require('./spawn'),
check_reqs = require('./check_reqs');
check_reqs = require('./check_reqs'),
fs = require('fs');
var projectPath = path.join(__dirname, '..', '..');
var projectName = null;
module.exports.run = function (argv) {
......@@ -36,6 +38,10 @@ module.exports.run = function (argv) {
'release': Boolean,
'device': Boolean,
'emulator': Boolean,
'codeSignIdentity': String,
'codeSignResourceRules': String,
'provisioningProfile': String,
'buildConfig' : String
}, {'-r': '--release'}, argv);
if (args.debug && args.release) {
......@@ -46,9 +52,41 @@ module.exports.run = function (argv) {
return Q.reject('Only one of "device"/"emulator" options should be specified');
}
if(args.buildConfig) {
if(!fs.existsSync(args.buildConfig)) {
return Q.reject('Build config file does not exist:' + args.buildConfig);
}
console.log('Reading build config file:', path.resolve(args.buildConfig));
var buildConfig = JSON.parse(fs.readFileSync(args.buildConfig, 'utf-8'));
if(buildConfig.ios) {
var buildType = args.release ? 'release' : 'debug';
var config = buildConfig.ios[buildType];
if(config) {
['codeSignIdentity', 'codeSignResourceRules', 'provisioningProfile'].forEach(
function(key) {
args[key] = args[key] || config[key];
});
}
}
}
return check_reqs.run().then(function () {
return findXCodeProjectIn(projectPath);
}).then(function (projectName) {
}).then(function (name) {
projectName = name;
var extraConfig = '';
if (args.codeSignIdentity) {
extraConfig += 'CODE_SIGN_IDENTITY = ' + args.codeSignIdentity + '\n';
extraConfig += 'CODE_SIGN_IDENTITY[sdk=iphoneos*] = ' + args.codeSignIdentity + '\n';
}
if (args.codeSignResourceRules) {
extraConfig += 'CODE_SIGN_RESOURCE_RULES_PATH = ' + args.codeSignResourceRules + '\n';
}
if (args.provisioningProfile) {
extraConfig += 'PROVISIONING_PROFILE = ' + args.provisioningProfile + '\n';
}
return Q.nfcall(fs.writeFile, path.join(__dirname, '..', 'build-extras.xcconfig'), extraConfig, 'utf-8');
}).then(function () {
var configuration = args.release ? 'Release' : 'Debug';
console.log('Building project : ' + path.join(projectPath, projectName + '.xcodeproj'));
......@@ -57,6 +95,23 @@ module.exports.run = function (argv) {
var xcodebuildArgs = getXcodeArgs(projectName, projectPath, configuration, args.device);
return spawn('xcodebuild', xcodebuildArgs, projectPath);
}).then(function () {
if (!args.device) {
return;
}
var buildOutputDir = path.join(projectPath, 'build', 'device');
var pathToApp = path.join(buildOutputDir, projectName + '.app');
var pathToIpa = path.join(buildOutputDir, projectName + '.ipa');
var xcRunArgs = ['-sdk', 'iphoneos', 'PackageApplication',
'-v', pathToApp,
'-o', pathToIpa];
if (args.codeSignIdentity) {
xcRunArgs.concat('--sign', args.codeSignIdentity);
}
if (args.provisioningProfile) {
xcRunArgs.concat('--embed', args.provisioningProfile);
}
return spawn('xcrun', xcRunArgs, projectPath);
});
};
......@@ -128,7 +183,10 @@ function getXcodeArgs(projectName, projectPath, configuration, isDevice) {
// help/usage function
module.exports.help = function help() {
console.log('');
console.log('Usage: build [ --debug | --release ] [--archs=\"<list of architectures...>\"] [--device | --simulator]');
console.log('Usage: build [--debug | --release] [--archs=\"<list of architectures...>\"]');
console.log(' [--device | --simulator] [--codeSignIdentity=\"<identity>\"]');
console.log(' [--codeSignResourceRules=\"<resourcerules path>\"]');
console.log(' [--provisioningProfile=\"<provisioning profile>\"]');
console.log(' --help : Displays this dialog.');
console.log(' --debug : Builds project in debug mode. (Default)');
console.log(' --release : Builds project in release mode.');
......@@ -137,10 +195,15 @@ module.exports.help = function help() {
// console.log(" --archs : Builds project binaries for specific chip architectures (`anycpu`, `arm`, `x86`, `x64`).");
console.log(' --device, --simulator');
console.log(' : Specifies, what type of project to build');
console.log(' --codeSignIdentity : Type of signing identity used for code signing.');
console.log(' --codeSignResourceRules : Path to ResourceRules.plist.');
console.log(' --provisioningProfile : UUID of the profile.');
console.log('');
console.log('examples:');
console.log(' build ');
console.log(' build --debug');
console.log(' build --release');
console.log(' build --codeSignIdentity="iPhone Distribution" --provisioningProfile="926c2bd6-8de9-4c2f-8407-1016d2d12954"');
// TODO: add support for building different archs
// console.log(" build --release --archs=\"armv7\"");
console.log('');
......
......@@ -17,34 +17,30 @@
under the License.
*/
/* jshint node:true, bitwise:true, undef:true, trailing:true, quotmark:true,
indent:4, unused:vars, latedef:nofunc,
sub:true, laxcomma:true, laxbreak:true
*/
var Q = require('Q'),
os = require('os'),
var Q = require('q'),
shell = require('shelljs'),
versions = require('./versions');
var XCODEBUILD_MIN_VERSION = '4.6.0';
var XCODEBUILD_NOT_FOUND_MESSAGE =
'Please install version ' + XCODEBUILD_MIN_VERSION + ' or greater from App Store';
var IOS_SIM_MIN_VERSION = '3.0.0';
var IOS_SIM_NOT_FOUND_MESSAGE = 'ios-sim was not found. Please download, build and install version ' + IOS_SIM_MIN_VERSION +
' or greater from https://github.com/phonegap/ios-sim into your path.' +
' Or \'npm install -g ios-sim\' using node.js: http://nodejs.org';
var IOS_SIM_NOT_FOUND_MESSAGE =
'Please download, build and install version ' + IOS_SIM_MIN_VERSION + ' or greater' +
' from https://github.com/phonegap/ios-sim into your path, or do \'npm install -g ios-sim\'';
var IOS_DEPLOY_MIN_VERSION = '1.2.0';
var IOS_DEPLOY_NOT_FOUND_MESSAGE = 'ios-deploy was not found. Please download, build and install version ' + IOS_DEPLOY_MIN_VERSION +
' or greater from https://github.com/phonegap/ios-deploy into your path.' +
' Or \'npm install -g ios-deploy\' using node.js: http://nodejs.org';
var IOS_DEPLOY_MIN_VERSION = '1.4.0';
var IOS_DEPLOY_NOT_FOUND_MESSAGE =
'Please download, build and install version ' + IOS_DEPLOY_MIN_VERSION + ' or greater' +
' from https://github.com/phonegap/ios-deploy into your path, or do \'npm install -g ios-deploy\'';
/**
* Checks if xcode util is available
* @return {Promise} Returns a promise either resolved with xcode version or rejected
*/
module.exports.run = module.exports.check_xcodebuild = function () {
return checkTool('xcodebuild', XCODEBUILD_MIN_VERSION);
return checkTool('xcodebuild', XCODEBUILD_MIN_VERSION, XCODEBUILD_NOT_FOUND_MESSAGE);
};
/**
......@@ -63,6 +59,13 @@ module.exports.check_ios_sim = function () {
return checkTool('ios-sim', IOS_SIM_MIN_VERSION, IOS_SIM_NOT_FOUND_MESSAGE);
};
module.exports.check_os = function () {
// Build iOS apps available for OSX platform only, so we reject on others platforms
return process.platform === 'darwin' ?
Q.resolve(process.platform) :
Q.reject('Cordova tooling for iOS requires Apple OS X');
};
module.exports.help = function () {
console.log('Usage: check_reqs or node check_reqs');
};
......@@ -71,24 +74,87 @@ module.exports.help = function () {
* Checks if specific tool is available.
* @param {String} tool Tool name to check. Known tools are 'xcodebuild', 'ios-sim' and 'ios-deploy'
* @param {Number} minVersion Min allowed tool version.
* @param {String} optMessage Message that will be used to reject promise.
* @param {String} message Message that will be used to reject promise.
* @return {Promise} Returns a promise either resolved with tool version or rejected
*/
function checkTool (tool, minVersion, optMessage) {
if (os.platform() !== 'darwin'){
// Build iOS apps available for OSX platform only, so we reject on others platforms
return Q.reject('Cordova tooling for iOS requires Apple OS X');
}
function checkTool (tool, minVersion, message) {
// Check whether tool command is available at all
var tool_command = shell.which(tool);
if (!tool_command) {
return Q.reject(optMessage || (tool + 'command is unavailable.'));
return Q.reject(tool + ' was not found. ' + (message || ''));
}
// check if tool version is greater than specified one
return versions.get_tool_version(tool).then(function (version) {
version = version.trim();
return versions.compareVersions(version, minVersion) >= 0 ?
Q.resolve(version) :
Q.reject('Cordova needs ' + tool + ' version ' + minVersion +
' or greater, you have version ' + version + '.');
' or greater, you have version ' + version + '. ' + (message || ''));
});
}
/**
* Object that represents one of requirements for current platform.
* @param {String} id The unique identifier for this requirements.
* @param {String} name The name of requirements. Human-readable field.
* @param {Boolean} isFatal Marks the requirement as fatal. If such requirement will fail
* next requirements' checks will be skipped.
*/
var Requirement = function (id, name, isFatal) {
this.id = id;
this.name = name;
this.installed = false;
this.metadata = {};
this.isFatal = isFatal || false;
};
/**
* Methods that runs all checks one by one and returns a result of checks
* as an array of Requirement objects. This method intended to be used by cordova-lib check_reqs method
*
* @return Promise<Requirement[]> Array of requirements. Due to implementation, promise is always fulfilled.
*/
module.exports.check_all = function() {
var requirements = [
new Requirement('os', 'Apple OS X', true),
new Requirement('xcode', 'Xcode'),
new Requirement('ios-deploy', 'ios-deploy'),
new Requirement('ios-sim', 'ios-sim')
];
var result = [];
var fatalIsHit = false;
var checkFns = [
module.exports.check_os,
module.exports.check_xcodebuild,
module.exports.check_ios_deploy,
module.exports.check_ios_sim
];
// Then execute requirement checks one-by-one
return checkFns.reduce(function (promise, checkFn, idx) {
return promise.then(function () {
// If fatal requirement is failed,
// we don't need to check others
if (fatalIsHit) return Q();
var requirement = requirements[idx];
return checkFn()
.then(function (version) {
requirement.installed = true;
requirement.metadata.version = version;
result.push(requirement);
}, function (err) {
if (requirement.isFatal) fatalIsHit = true;
requirement.metadata.reason = err;
result.push(requirement);
});
});
}, Q())
.then(function () {
// When chain is completed, return requirements array to upstream API
return result;
});
};
#!/usr/bin/env node
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
// This script copies the www directory into the Xcode project.
// This script should not be called directly.
// It is called as a build step from Xcode.
var BUILT_PRODUCTS_DIR = process.env.BUILT_PRODUCTS_DIR,
FULL_PRODUCT_NAME = process.env.FULL_PRODUCT_NAME,
COPY_HIDDEN = process.env.COPY_HIDDEN,
PROJECT_FILE_PATH = process.env.PROJECT_FILE_PATH;
var path = require('path'),
fs = require('fs'),
shell = require('shelljs'),
glob = require('glob'),
srcDir = 'www',
dstDir = path.join(BUILT_PRODUCTS_DIR, FULL_PRODUCT_NAME),
dstWwwDir = path.join(dstDir, 'www');
if(!BUILT_PRODUCTS_DIR) {
console.error('The script is meant to be run as an Xcode build step and relies on env variables set by Xcode.');
process.exit(1);
}
try {
fs.statSync(srcDir);
} catch (e) {
console.error('Path does not exist: ' + srcDir);
process.exit(1);
}
// Code signing files must be removed or else there are
// resource signing errors.
shell.rm('-rf', dstWwwDir);
shell.rm('-rf', path.join(dstDir, '_CodeSignature'));
shell.rm('-rf', path.join(dstDir, 'PkgInfo'));
shell.rm('-rf', path.join(dstDir, 'embedded.mobileprovision'));
// Copy www dir recursively
if(!!COPY_HIDDEN) {
shell.mkdir('-p', dstWwwDir);
shell.cp('-r', glob.sync(srcDir + '/**', { dot: true }), dstWwwDir);
} else {
shell.cp('-r', srcDir, dstDir);
}
// Copy the config.xml file.
shell.cp('-f', path.join(path.dirname(PROJECT_FILE_PATH), path.basename(PROJECT_FILE_PATH, '.xcodeproj'), 'config.xml'),
dstDir);
#!/bin/sh
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
#
# This script copies the www directory into the Xcode project.
#
# This script should not be called directly.
# It is called as a build step from Xcode.
SRC_DIR="www/"
DST_DIR="$BUILT_PRODUCTS_DIR/$FULL_PRODUCT_NAME/www"
COPY_HIDDEN=
ORIG_IFS=$IFS
IFS=$(echo -en "\n\b")
if [[ -z "$BUILT_PRODUCTS_DIR" ]]; then
echo "The script is meant to be run as an Xcode build step and relies on env variables set by Xcode."
exit 1
fi
if [[ ! -e "$SRC_DIR" ]]; then
echo "Path does not exist: $SRC_DIR"
exit 1
fi
# Use full path to find to avoid conflict with macports find (CB-6383).
if [[ -n $COPY_HIDDEN ]]; then
alias do_find='/usr/bin/find "$SRC_DIR"'
else
alias do_find='/usr/bin/find -L "$SRC_DIR" -name ".*" -prune -o'
fi
time (
# Code signing files must be removed or else there are
# resource signing errors.
rm -rf "$DST_DIR" \
"$BUILT_PRODUCTS_DIR/$FULL_PRODUCT_NAME/_CodeSignature" \
"$BUILT_PRODUCTS_DIR/$FULL_PRODUCT_NAME/PkgInfo" \
"$BUILT_PRODUCTS_DIR/$FULL_PRODUCT_NAME/embedded.mobileprovision"
# Directories
for p in $(do_find -type d -print); do
subpath="${p#$SRC_DIR}"
mkdir "$DST_DIR$subpath" || exit 1
done
# Symlinks
for p in $(do_find -type l -print); do
subpath="${p#$SRC_DIR}"
source=$(readlink $SRC_DIR$subpath)
sourcetype=$(stat -f "%HT%SY" $source)
if [ "$sourcetype" = "Directory" ]; then
mkdir "$DST_DIR$subpath" || exit 2
else
rsync -a "$source" "$DST_DIR$subpath" || exit 3
fi
done
# Files
for p in $(do_find -type f -print); do
subpath="${p#$SRC_DIR}"
if ! ln "$SRC_DIR$subpath" "$DST_DIR$subpath" 2>/dev/null; then
rsync -a "$SRC_DIR$subpath" "$DST_DIR$subpath" || exit 4
fi
done
# Copy the config.xml file.
cp -f "${PROJECT_FILE_PATH%.xcodeproj}/config.xml" "$BUILT_PRODUCTS_DIR/$FULL_PRODUCT_NAME"
)
IFS=$ORIG_IFS
......@@ -21,7 +21,7 @@
/*jshint node: true*/
var Q = require('Q'),
var Q = require('q'),
exec = require('child_process').exec;
/**
......@@ -36,13 +36,19 @@ function listDevices() {
];
// wrap al lexec calls into promises and wait until they're fullfilled
return Q.all(commands).then(function (promises) {
return Q.all(commands).then(function (results) {
var accumulator = [];
promises.forEach(function (promise) {
if (promise.state === 'fulfilled') {
results.forEach(function (result) {
var devicefound;
// Each command promise resolves with array [stout, stderr], and we need stdout only
// Append stdout lines to accumulator
accumulator.concat(promise.value[0].trim().split('\n'));
devicefound = result[0].trim().split('\n');
if(devicefound && devicefound.length) {
devicefound.forEach(function(device) {
if (device) {
accumulator.push(device);
}
});
}
});
return accumulator;
......
......@@ -32,8 +32,7 @@ var Q = require('q'),
function listEmulatorImages () {
return check_reqs.check_ios_sim().then(function () {
return Q.nfcall(exec, 'ios-sim showdevicetypes 2>&1 | ' +
'sed "s/com.apple.CoreSimulator.SimDeviceType.//g" | ' +
'awk -F\',\' \'{print $1}\'');
'sed "s/com.apple.CoreSimulator.SimDeviceType.//g"');
}).then(function (stdio) {
// Exec promise resolves with array [stout, stderr], and we need stdout only
return stdio[0].trim().split('\n');
......
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.
exports.alphasort = alphasort
exports.alphasorti = alphasorti
exports.setopts = setopts
exports.ownProp = ownProp
exports.makeAbs = makeAbs
exports.finish = finish
exports.mark = mark
exports.isIgnored = isIgnored
exports.childrenIgnored = childrenIgnored
function ownProp (obj, field) {
return Object.prototype.hasOwnProperty.call(obj, field)
}
var path = require("path")
var minimatch = require("minimatch")
var isAbsolute = require("path-is-absolute")
var Minimatch = minimatch.Minimatch
function alphasorti (a, b) {
return a.toLowerCase().localeCompare(b.toLowerCase())
}
function alphasort (a, b) {
return a.localeCompare(b)
}
function setupIgnores (self, options) {
self.ignore = options.ignore || []
if (!Array.isArray(self.ignore))
self.ignore = [self.ignore]
if (self.ignore.length) {
self.ignore = self.ignore.map(ignoreMap)
}
}
function ignoreMap (pattern) {
var gmatcher = null
if (pattern.slice(-3) === '/**') {
var gpattern = pattern.replace(/(\/\*\*)+$/, '')
gmatcher = new Minimatch(gpattern)
}
return {
matcher: new Minimatch(pattern),
gmatcher: gmatcher
}
}
function setopts (self, pattern, options) {
if (!options)
options = {}
// base-matching: just use globstar for that.
if (options.matchBase && -1 === pattern.indexOf("/")) {
if (options.noglobstar) {
throw new Error("base matching requires globstar")
}
pattern = "**/" + pattern
}
self.silent = !!options.silent
self.pattern = pattern
self.strict = options.strict !== false
self.realpath = !!options.realpath
self.realpathCache = options.realpathCache || Object.create(null)
self.follow = !!options.follow
self.dot = !!options.dot
self.mark = !!options.mark
self.nodir = !!options.nodir
if (self.nodir)
self.mark = true
self.sync = !!options.sync
self.nounique = !!options.nounique
self.nonull = !!options.nonull
self.nosort = !!options.nosort
self.nocase = !!options.nocase
self.stat = !!options.stat
self.noprocess = !!options.noprocess
self.maxLength = options.maxLength || Infinity
self.cache = options.cache || Object.create(null)
self.statCache = options.statCache || Object.create(null)
self.symlinks = options.symlinks || Object.create(null)
setupIgnores(self, options)
self.changedCwd = false
var cwd = process.cwd()
if (!ownProp(options, "cwd"))
self.cwd = cwd
else {
self.cwd = options.cwd
self.changedCwd = path.resolve(options.cwd) !== cwd
}
self.root = options.root || path.resolve(self.cwd, "/")
self.root = path.resolve(self.root)
if (process.platform === "win32")
self.root = self.root.replace(/\\/g, "/")
self.nomount = !!options.nomount
// disable comments and negation unless the user explicitly
// passes in false as the option.
options.nonegate = options.nonegate === false ? false : true
options.nocomment = options.nocomment === false ? false : true
deprecationWarning(options)
self.minimatch = new Minimatch(pattern, options)
self.options = self.minimatch.options
}
// TODO(isaacs): remove entirely in v6
// exported to reset in tests
exports.deprecationWarned
function deprecationWarning(options) {
if (!options.nonegate || !options.nocomment) {
if (process.noDeprecation !== true && !exports.deprecationWarned) {
var msg = 'glob WARNING: comments and negation will be disabled in v6'
if (process.throwDeprecation)
throw new Error(msg)
else if (process.traceDeprecation)
console.trace(msg)
else
console.error(msg)
exports.deprecationWarned = true
}
}
}
function finish (self) {
var nou = self.nounique
var all = nou ? [] : Object.create(null)
for (var i = 0, l = self.matches.length; i < l; i ++) {
var matches = self.matches[i]
if (!matches || Object.keys(matches).length === 0) {
if (self.nonull) {
// do like the shell, and spit out the literal glob
var literal = self.minimatch.globSet[i]
if (nou)
all.push(literal)
else
all[literal] = true
}
} else {
// had matches
var m = Object.keys(matches)
if (nou)
all.push.apply(all, m)
else
m.forEach(function (m) {
all[m] = true
})
}
}
if (!nou)
all = Object.keys(all)
if (!self.nosort)
all = all.sort(self.nocase ? alphasorti : alphasort)
// at *some* point we statted all of these
if (self.mark) {
for (var i = 0; i < all.length; i++) {
all[i] = self._mark(all[i])
}
if (self.nodir) {
all = all.filter(function (e) {
return !(/\/$/.test(e))
})
}
}
if (self.ignore.length)
all = all.filter(function(m) {
return !isIgnored(self, m)
})
self.found = all
}
function mark (self, p) {
var abs = makeAbs(self, p)
var c = self.cache[abs]
var m = p
if (c) {
var isDir = c === 'DIR' || Array.isArray(c)
var slash = p.slice(-1) === '/'
if (isDir && !slash)
m += '/'
else if (!isDir && slash)
m = m.slice(0, -1)
if (m !== p) {
var mabs = makeAbs(self, m)
self.statCache[mabs] = self.statCache[abs]
self.cache[mabs] = self.cache[abs]
}
}
return m
}
// lotta situps...
function makeAbs (self, f) {
var abs = f
if (f.charAt(0) === '/') {
abs = path.join(self.root, f)
} else if (isAbsolute(f) || f === '') {
abs = f
} else if (self.changedCwd) {
abs = path.resolve(self.cwd, f)
} else {
abs = path.resolve(f)
}
return abs
}
// Return true, if pattern ends with globstar '**', for the accompanying parent directory.
// Ex:- If node_modules/** is the pattern, add 'node_modules' to ignore list along with it's contents
function isIgnored (self, path) {
if (!self.ignore.length)
return false
return self.ignore.some(function(item) {
return item.matcher.match(path) || !!(item.gmatcher && item.gmatcher.match(path))
})
}
function childrenIgnored (self, path) {
if (!self.ignore.length)
return false
return self.ignore.some(function(item) {
return !!(item.gmatcher && item.gmatcher.match(path))
})
}
{
"env" : {
"node" : true
},
"rules" : {
"semi": [2, "never"],
"strict": 0,
"quotes": [1, "single", "avoid-escape"],
"no-use-before-define": 0,
"curly": 0,
"no-underscore-dangle": 0,
"no-lonely-if": 1,
"no-unused-vars": [2, {"vars" : "all", "args" : "after-used"}],
"no-mixed-requires": 0,
"space-infix-ops": 0
}
}
The ISC License
Copyright (c) Isaac Z. Schlueter
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.
# inflight
Add callbacks to requests in flight to avoid async duplication
## USAGE
```javascript
var inflight = require('inflight')
// some request that does some stuff
function req(key, callback) {
// key is any random string. like a url or filename or whatever.
//
// will return either a falsey value, indicating that the
// request for this key is already in flight, or a new callback
// which when called will call all callbacks passed to inflightk
// with the same key
callback = inflight(key, callback)
// If we got a falsey value back, then there's already a req going
if (!callback) return
// this is where you'd fetch the url or whatever
// callback is also once()-ified, so it can safely be assigned
// to multiple events etc. First call wins.
setTimeout(function() {
callback(null, key)
}, 100)
}
// only assigns a single setTimeout
// when it dings, all cbs get called
req('foo', cb1)
req('foo', cb2)
req('foo', cb3)
req('foo', cb4)
```
var wrappy = require('wrappy')
var reqs = Object.create(null)
var once = require('once')
module.exports = wrappy(inflight)
function inflight (key, cb) {
if (reqs[key]) {
reqs[key].push(cb)
return null
} else {
reqs[key] = [cb]
return makeres(key)
}
}
function makeres (key) {
return once(function RES () {
var cbs = reqs[key]
var len = cbs.length
var args = slice(arguments)
for (var i = 0; i < len; i++) {
cbs[i].apply(null, args)
}
if (cbs.length > len) {
// added more in the interim.
// de-zalgo, just in case, but don't call again.
cbs.splice(0, len)
process.nextTick(function () {
RES.apply(null, args)
})
} else {
delete reqs[key]
}
})
}
function slice (args) {
var length = args.length
var array = []
for (var i = 0; i < length; i++) array[i] = args[i]
return array
}
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.
# wrappy
Callback wrapping utility
## USAGE
```javascript
var wrappy = require("wrappy")
// var wrapper = wrappy(wrapperFunction)
// make sure a cb is called only once
// See also: http://npm.im/once for this specific use case
var once = wrappy(function (cb) {
var called = false
return function () {
if (called) return
called = true
return cb.apply(this, arguments)
}
})
function printBoo () {
console.log('boo')
}
// has some rando property
printBoo.iAmBooPrinter = true
var onlyPrintOnce = once(printBoo)
onlyPrintOnce() // prints 'boo'
onlyPrintOnce() // does nothing
// random property is retained!
assert.equal(onlyPrintOnce.iAmBooPrinter, true)
```
{
"name": "wrappy",
"version": "1.0.1",
"description": "Callback wrapping utility",
"main": "wrappy.js",
"directories": {
"test": "test"
},
"dependencies": {},
"devDependencies": {
"tap": "^0.4.12"
},
"scripts": {
"test": "tap test/*.js"
},
"repository": {
"type": "git",
"url": "https://github.com/npm/wrappy"
},
"author": {
"name": "Isaac Z. Schlueter",
"email": "i@izs.me",
"url": "http://blog.izs.me/"
},
"license": "ISC",
"bugs": {
"url": "https://github.com/npm/wrappy/issues"
},
"homepage": "https://github.com/npm/wrappy",
"readme": "# wrappy\n\nCallback wrapping utility\n\n## USAGE\n\n```javascript\nvar wrappy = require(\"wrappy\")\n\n// var wrapper = wrappy(wrapperFunction)\n\n// make sure a cb is called only once\n// See also: http://npm.im/once for this specific use case\nvar once = wrappy(function (cb) {\n var called = false\n return function () {\n if (called) return\n called = true\n return cb.apply(this, arguments)\n }\n})\n\nfunction printBoo () {\n console.log('boo')\n}\n// has some rando property\nprintBoo.iAmBooPrinter = true\n\nvar onlyPrintOnce = once(printBoo)\n\nonlyPrintOnce() // prints 'boo'\nonlyPrintOnce() // does nothing\n\n// random property is retained!\nassert.equal(onlyPrintOnce.iAmBooPrinter, true)\n```\n",
"readmeFilename": "README.md",
"_id": "wrappy@1.0.1",
"_shasum": "1e65969965ccbc2db4548c6b84a6f2c5aedd4739",
"_resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz",
"_from": "wrappy@>=1.0.0 <2.0.0"
}
var test = require('tap').test
var wrappy = require('../wrappy.js')
test('basic', function (t) {
function onceifier (cb) {
var called = false
return function () {
if (called) return
called = true
return cb.apply(this, arguments)
}
}
onceifier.iAmOnce = {}
var once = wrappy(onceifier)
t.equal(once.iAmOnce, onceifier.iAmOnce)
var called = 0
function boo () {
t.equal(called, 0)
called++
}
// has some rando property
boo.iAmBoo = true
var onlyPrintOnce = once(boo)
onlyPrintOnce() // prints 'boo'
onlyPrintOnce() // does nothing
t.equal(called, 1)
// random property is retained!
t.equal(onlyPrintOnce.iAmBoo, true)
var logs = []
var logwrap = wrappy(function (msg, cb) {
logs.push(msg + ' wrapping cb')
return function () {
logs.push(msg + ' before cb')
var ret = cb.apply(this, arguments)
logs.push(msg + ' after cb')
}
})
var c = logwrap('foo', function () {
t.same(logs, [ 'foo wrapping cb', 'foo before cb' ])
})
c()
t.same(logs, [ 'foo wrapping cb', 'foo before cb', 'foo after cb' ])
t.end()
})
// Returns a wrapper function that returns a wrapped callback
// The wrapper function should do some stuff, and return a
// presumably different callback function.
// This makes sure that own properties are retained, so that
// decorations and such are not lost along the way.
module.exports = wrappy
function wrappy (fn, cb) {
if (fn && cb) return wrappy(fn)(cb)
if (typeof fn !== 'function')
throw new TypeError('need wrapper function')
Object.keys(fn).forEach(function (k) {
wrapper[k] = fn[k]
})
return wrapper
function wrapper() {
var args = new Array(arguments.length)
for (var i = 0; i < args.length; i++) {
args[i] = arguments[i]
}
var ret = fn.apply(this, args)
var cb = args[args.length-1]
if (typeof ret === 'function' && ret !== cb) {
Object.keys(cb).forEach(function (k) {
ret[k] = cb[k]
})
}
return ret
}
}
{
"name": "inflight",
"version": "1.0.4",
"description": "Add callbacks to requests in flight to avoid async duplication",
"main": "inflight.js",
"dependencies": {
"once": "^1.3.0",
"wrappy": "1"
},
"devDependencies": {
"tap": "^0.4.10"
},
"scripts": {
"test": "tap test.js"
},
"repository": {
"type": "git",
"url": "git://github.com/isaacs/inflight"
},
"author": {
"name": "Isaac Z. Schlueter",
"email": "i@izs.me",
"url": "http://blog.izs.me/"
},
"bugs": {
"url": "https://github.com/isaacs/inflight/issues"
},
"homepage": "https://github.com/isaacs/inflight",
"license": "ISC",
"gitHead": "c7b5531d572a867064d4a1da9e013e8910b7d1ba",
"_id": "inflight@1.0.4",
"_shasum": "6cbb4521ebd51ce0ec0a936bfd7657ef7e9b172a",
"_from": "inflight@>=1.0.4 <2.0.0",
"_npmVersion": "2.1.3",
"_nodeVersion": "0.10.32",
"_npmUser": {
"name": "othiym23",
"email": "ogd@aoaioxxysz.net"
},
"maintainers": [
{
"name": "isaacs",
"email": "i@izs.me"
},
{
"name": "othiym23",
"email": "ogd@aoaioxxysz.net"
},
{
"name": "iarna",
"email": "me@re-becca.org"
}
],
"dist": {
"shasum": "6cbb4521ebd51ce0ec0a936bfd7657ef7e9b172a",
"tarball": "http://registry.npmjs.org/inflight/-/inflight-1.0.4.tgz"
},
"directories": {},
"_resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.4.tgz",
"readme": "ERROR: No README data found!"
}
var test = require('tap').test
var inf = require('./inflight.js')
function req (key, cb) {
cb = inf(key, cb)
if (cb) setTimeout(function () {
cb(key)
cb(key)
})
return cb
}
test('basic', function (t) {
var calleda = false
var a = req('key', function (k) {
t.notOk(calleda)
calleda = true
t.equal(k, 'key')
if (calledb) t.end()
})
t.ok(a, 'first returned cb function')
var calledb = false
var b = req('key', function (k) {
t.notOk(calledb)
calledb = true
t.equal(k, 'key')
if (calleda) t.end()
})
t.notOk(b, 'second should get falsey inflight response')
})
test('timing', function (t) {
var expect = [
'method one',
'start one',
'end one',
'two',
'tick',
'three'
]
var i = 0
function log (m) {
t.equal(m, expect[i], m + ' === ' + expect[i])
++i
if (i === expect.length)
t.end()
}
function method (name, cb) {
log('method ' + name)
process.nextTick(cb)
}
var one = inf('foo', function () {
log('start one')
var three = inf('foo', function () {
log('three')
})
if (three) method('three', three)
log('end one')
})
method('one', one)
var two = inf('foo', function () {
log('two')
})
if (two) method('one', two)
process.nextTick(log.bind(null, 'tick'))
})
test('parameters', function (t) {
t.plan(8)
var a = inf('key', function (first, second, third) {
t.equal(first, 1)
t.equal(second, 2)
t.equal(third, 3)
})
t.ok(a, 'first returned cb function')
var b = inf('key', function (first, second, third) {
t.equal(first, 1)
t.equal(second, 2)
t.equal(third, 3)
})
t.notOk(b, 'second should get falsey inflight response')
setTimeout(function () {
a(1, 2, 3)
})
})
The ISC License
Copyright (c) Isaac Z. Schlueter
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.
Browser-friendly inheritance fully compatible with standard node.js
[inherits](http://nodejs.org/api/util.html#util_util_inherits_constructor_superconstructor).
This package exports standard `inherits` from node.js `util` module in
node environment, but also provides alternative browser-friendly
implementation through [browser
field](https://gist.github.com/shtylman/4339901). Alternative
implementation is a literal copy of standard one located in standalone
module to avoid requiring of `util`. It also has a shim for old
browsers with no `Object.create` support.
While keeping you sure you are using standard `inherits`
implementation in node.js environment, it allows bundlers such as
[browserify](https://github.com/substack/node-browserify) to not
include full `util` package to your client code if all you need is
just `inherits` function. It worth, because browser shim for `util`
package is large and `inherits` is often the single function you need
from it.
It's recommended to use this package instead of
`require('util').inherits` for any code that has chances to be used
not only in node.js but in browser too.
## usage
```js
var inherits = require('inherits');
// then use exactly as the standard one
```
## note on version ~1.0
Version ~1.0 had completely different motivation and is not compatible
neither with 2.0 nor with standard node.js `inherits`.
If you are using version ~1.0 and planning to switch to ~2.0, be
careful:
* new version uses `super_` instead of `super` for referencing
superclass
* new version overwrites current prototype while old one preserves any
existing fields on it
if (typeof Object.create === 'function') {
// implementation from standard node.js 'util' module
module.exports = function inherits(ctor, superCtor) {
ctor.super_ = superCtor
ctor.prototype = Object.create(superCtor.prototype, {
constructor: {
value: ctor,
enumerable: false,
writable: true,
configurable: true
}
});
};
} else {
// old school shim for old browsers
module.exports = function inherits(ctor, superCtor) {
ctor.super_ = superCtor
var TempCtor = function () {}
TempCtor.prototype = superCtor.prototype
ctor.prototype = new TempCtor()
ctor.prototype.constructor = ctor
}
}
{
"name": "inherits",
"description": "Browser-friendly inheritance fully compatible with standard node.js inherits()",
"version": "2.0.1",
"keywords": [
"inheritance",
"class",
"klass",
"oop",
"object-oriented",
"inherits",
"browser",
"browserify"
],
"main": "./inherits.js",
"browser": "./inherits_browser.js",
"repository": {
"type": "git",
"url": "git://github.com/isaacs/inherits"
},
"license": "ISC",
"scripts": {
"test": "node test"
},
"readme": "Browser-friendly inheritance fully compatible with standard node.js\n[inherits](http://nodejs.org/api/util.html#util_util_inherits_constructor_superconstructor).\n\nThis package exports standard `inherits` from node.js `util` module in\nnode environment, but also provides alternative browser-friendly\nimplementation through [browser\nfield](https://gist.github.com/shtylman/4339901). Alternative\nimplementation is a literal copy of standard one located in standalone\nmodule to avoid requiring of `util`. It also has a shim for old\nbrowsers with no `Object.create` support.\n\nWhile keeping you sure you are using standard `inherits`\nimplementation in node.js environment, it allows bundlers such as\n[browserify](https://github.com/substack/node-browserify) to not\ninclude full `util` package to your client code if all you need is\njust `inherits` function. It worth, because browser shim for `util`\npackage is large and `inherits` is often the single function you need\nfrom it.\n\nIt's recommended to use this package instead of\n`require('util').inherits` for any code that has chances to be used\nnot only in node.js but in browser too.\n\n## usage\n\n```js\nvar inherits = require('inherits');\n// then use exactly as the standard one\n```\n\n## note on version ~1.0\n\nVersion ~1.0 had completely different motivation and is not compatible\nneither with 2.0 nor with standard node.js `inherits`.\n\nIf you are using version ~1.0 and planning to switch to ~2.0, be\ncareful:\n\n* new version uses `super_` instead of `super` for referencing\n superclass\n* new version overwrites current prototype while old one preserves any\n existing fields on it\n",
"readmeFilename": "README.md",
"bugs": {
"url": "https://github.com/isaacs/inherits/issues"
},
"homepage": "https://github.com/isaacs/inherits",
"_id": "inherits@2.0.1",
"_shasum": "b17d08d326b4423e568eff719f91b0b1cbdf69f1",
"_resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
"_from": "inherits@>=2.0.0 <3.0.0"
}
var inherits = require('./inherits.js')
var assert = require('assert')
function test(c) {
assert(c.constructor === Child)
assert(c.constructor.super_ === Parent)
assert(Object.getPrototypeOf(c) === Child.prototype)
assert(Object.getPrototypeOf(Object.getPrototypeOf(c)) === Parent.prototype)
assert(c instanceof Child)
assert(c instanceof Parent)
}
function Child() {
Parent.call(this)
test(this)
}
function Parent() {}
inherits(Child, Parent)
var c = new Child
test(c)
console.log('ok')
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.
# minimatch
A minimal matching utility.
[![Build Status](https://secure.travis-ci.org/isaacs/minimatch.png)](http://travis-ci.org/isaacs/minimatch)
This is the matching library used internally by npm.
It works by converting glob expressions into JavaScript `RegExp`
objects.
## Usage
```javascript
var minimatch = require("minimatch")
minimatch("bar.foo", "*.foo") // true!
minimatch("bar.foo", "*.bar") // false!
minimatch("bar.foo", "*.+(bar|foo)", { debug: true }) // true, and noisy!
```
## Features
Supports these glob features:
* Brace Expansion
* Extended glob matching
* "Globstar" `**` matching
See:
* `man sh`
* `man bash`
* `man 3 fnmatch`
* `man 5 gitignore`
## Minimatch Class
Create a minimatch object by instanting the `minimatch.Minimatch` class.
```javascript
var Minimatch = require("minimatch").Minimatch
var mm = new Minimatch(pattern, options)
```
### Properties
* `pattern` The original pattern the minimatch object represents.
* `options` The options supplied to the constructor.
* `set` A 2-dimensional array of regexp or string expressions.
Each row in the
array corresponds to a brace-expanded pattern. Each item in the row
corresponds to a single path-part. For example, the pattern
`{a,b/c}/d` would expand to a set of patterns like:
[ [ a, d ]
, [ b, c, d ] ]
If a portion of the pattern doesn't have any "magic" in it
(that is, it's something like `"foo"` rather than `fo*o?`), then it
will be left as a string rather than converted to a regular
expression.
* `regexp` Created by the `makeRe` method. A single regular expression
expressing the entire pattern. This is useful in cases where you wish
to use the pattern somewhat like `fnmatch(3)` with `FNM_PATH` enabled.
* `negate` True if the pattern is negated.
* `comment` True if the pattern is a comment.
* `empty` True if the pattern is `""`.
### Methods
* `makeRe` Generate the `regexp` member if necessary, and return it.
Will return `false` if the pattern is invalid.
* `match(fname)` Return true if the filename matches the pattern, or
false otherwise.
* `matchOne(fileArray, patternArray, partial)` Take a `/`-split
filename, and match it against a single row in the `regExpSet`. This
method is mainly for internal use, but is exposed so that it can be
used by a glob-walker that needs to avoid excessive filesystem calls.
All other methods are internal, and will be called as necessary.
## Functions
The top-level exported function has a `cache` property, which is an LRU
cache set to store 100 items. So, calling these methods repeatedly
with the same pattern and options will use the same Minimatch object,
saving the cost of parsing it multiple times.
### minimatch(path, pattern, options)
Main export. Tests a path against the pattern using the options.
```javascript
var isJS = minimatch(file, "*.js", { matchBase: true })
```
### minimatch.filter(pattern, options)
Returns a function that tests its
supplied argument, suitable for use with `Array.filter`. Example:
```javascript
var javascripts = fileList.filter(minimatch.filter("*.js", {matchBase: true}))
```
### minimatch.match(list, pattern, options)
Match against the list of
files, in the style of fnmatch or glob. If nothing is matched, and
options.nonull is set, then return a list containing the pattern itself.
```javascript
var javascripts = minimatch.match(fileList, "*.js", {matchBase: true}))
```
### minimatch.makeRe(pattern, options)
Make a regular expression object from the pattern.
## Options
All options are `false` by default.
### debug
Dump a ton of stuff to stderr.
### nobrace
Do not expand `{a,b}` and `{1..3}` brace sets.
### noglobstar
Disable `**` matching against multiple folder names.
### dot
Allow patterns to match filenames starting with a period, even if
the pattern does not explicitly have a period in that spot.
Note that by default, `a/**/b` will **not** match `a/.d/b`, unless `dot`
is set.
### noext
Disable "extglob" style patterns like `+(a|b)`.
### nocase
Perform a case-insensitive match.
### nonull
When a match is not found by `minimatch.match`, return a list containing
the pattern itself if this option is set. When not set, an empty list
is returned if there are no matches.
### matchBase
If set, then patterns without slashes will be matched
against the basename of the path if it contains slashes. For example,
`a?b` would match the path `/xyz/123/acb`, but not `/xyz/acb/123`.
### nocomment
Suppress the behavior of treating `#` at the start of a pattern as a
comment.
### nonegate
Suppress the behavior of treating a leading `!` character as negation.
### flipNegate
Returns from negate expressions the same as if they were not negated.
(Ie, true on a hit, false on a miss.)
## Comparisons to other fnmatch/glob implementations
While strict compliance with the existing standards is a worthwhile
goal, some discrepancies exist between minimatch and other
implementations, and are intentional.
If the pattern starts with a `!` character, then it is negated. Set the
`nonegate` flag to suppress this behavior, and treat leading `!`
characters normally. This is perhaps relevant if you wish to start the
pattern with a negative extglob pattern like `!(a|B)`. Multiple `!`
characters at the start of a pattern will negate the pattern multiple
times.
If a pattern starts with `#`, then it is treated as a comment, and
will not match anything. Use `\#` to match a literal `#` at the
start of a line, or set the `nocomment` flag to suppress this behavior.
The double-star character `**` is supported by default, unless the
`noglobstar` flag is set. This is supported in the manner of bsdglob
and bash 4.1, where `**` only has special significance if it is the only
thing in a path part. That is, `a/**/b` will match `a/x/y/b`, but
`a/**b` will not.
If an escaped pattern has no matches, and the `nonull` flag is set,
then minimatch.match returns the pattern as-provided, rather than
interpreting the character escapes. For example,
`minimatch.match([], "\\*a\\?")` will return `"\\*a\\?"` rather than
`"*a?"`. This is akin to setting the `nullglob` option in bash, except
that it does not resolve escaped pattern characters.
If brace expansion is not disabled, then it is performed before any
other interpretation of the glob pattern. Thus, a pattern like
`+(a|{b),c)}`, which would not be valid in bash or zsh, is expanded
**first** into the set of `+(a|b)` and `+(a|c)`, and those patterns are
checked for validity. Since those two are valid, matching proceeds.
# brace-expansion
[Brace expansion](https://www.gnu.org/software/bash/manual/html_node/Brace-Expansion.html),
as known from sh/bash, in JavaScript.
[![build status](https://secure.travis-ci.org/juliangruber/brace-expansion.svg)](http://travis-ci.org/juliangruber/brace-expansion)
[![testling badge](https://ci.testling.com/juliangruber/brace-expansion.png)](https://ci.testling.com/juliangruber/brace-expansion)
## Example
```js
var expand = require('brace-expansion');
expand('file-{a,b,c}.jpg')
// => ['file-a.jpg', 'file-b.jpg', 'file-c.jpg']
expand('-v{,,}')
// => ['-v', '-v', '-v']
expand('file{0..2}.jpg')
// => ['file0.jpg', 'file1.jpg', 'file2.jpg']
expand('file-{a..c}.jpg')
// => ['file-a.jpg', 'file-b.jpg', 'file-c.jpg']
expand('file{2..0}.jpg')
// => ['file2.jpg', 'file1.jpg', 'file0.jpg']
expand('file{0..4..2}.jpg')
// => ['file0.jpg', 'file2.jpg', 'file4.jpg']
expand('file-{a..e..2}.jpg')
// => ['file-a.jpg', 'file-c.jpg', 'file-e.jpg']
expand('file{00..10..5}.jpg')
// => ['file00.jpg', 'file05.jpg', 'file10.jpg']
expand('{{A..C},{a..c}}')
// => ['A', 'B', 'C', 'a', 'b', 'c']
expand('ppp{,config,oe{,conf}}')
// => ['ppp', 'pppconfig', 'pppoe', 'pppoeconf']
```
## API
```js
var expand = require('brace-expansion');
```
### var expanded = expand(str)
Return an array of all possible and valid expansions of `str`. If none are
found, `[str]` is returned.
Valid expansions are:
```js
/^(.*,)+(.+)?$/
// {a,b,...}
```
A comma seperated list of options, like `{a,b}` or `{a,{b,c}}` or `{,a,}`.
```js
/^-?\d+\.\.-?\d+(\.\.-?\d+)?$/
// {x..y[..incr]}
```
A numeric sequence from `x` to `y` inclusive, with optional increment.
If `x` or `y` start with a leading `0`, all the numbers will be padded
to have equal length. Negative numbers and backwards iteration work too.
```js
/^-?\d+\.\.-?\d+(\.\.-?\d+)?$/
// {x..y[..incr]}
```
An alphabetic sequence from `x` to `y` inclusive, with optional increment.
`x` and `y` must be exactly one character, and if given, `incr` must be a
number.
For compatibility reasons, the string `${` is not eligible for brace expansion.
## Installation
With [npm](https://npmjs.org) do:
```bash
npm install brace-expansion
```
## Contributors
- [Julian Gruber](https://github.com/juliangruber)
- [Isaac Z. Schlueter](https://github.com/isaacs)
## License
(MIT)
Copyright (c) 2013 Julian Gruber &lt;julian@juliangruber.com&gt;
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.
var expand = require('./');
console.log(expand('http://any.org/archive{1996..1999}/vol{1..4}/part{a,b,c}.html'));
console.log(expand('http://www.numericals.com/file{1..100..10}.txt'));
console.log(expand('http://www.letters.com/file{a..z..2}.txt'));
console.log(expand('mkdir /usr/local/src/bash/{old,new,dist,bugs}'));
console.log(expand('chown root /usr/{ucb/{ex,edit},lib/{ex?.?*,how_ex}}'));
var concatMap = require('concat-map');
var balanced = require('balanced-match');
module.exports = expandTop;
var escSlash = '\0SLASH'+Math.random()+'\0';
var escOpen = '\0OPEN'+Math.random()+'\0';
var escClose = '\0CLOSE'+Math.random()+'\0';
var escComma = '\0COMMA'+Math.random()+'\0';
var escPeriod = '\0PERIOD'+Math.random()+'\0';
function numeric(str) {
return parseInt(str, 10) == str
? parseInt(str, 10)
: str.charCodeAt(0);
}
function escapeBraces(str) {
return str.split('\\\\').join(escSlash)
.split('\\{').join(escOpen)
.split('\\}').join(escClose)
.split('\\,').join(escComma)
.split('\\.').join(escPeriod);
}
function unescapeBraces(str) {
return str.split(escSlash).join('\\')
.split(escOpen).join('{')
.split(escClose).join('}')
.split(escComma).join(',')
.split(escPeriod).join('.');
}
// Basically just str.split(","), but handling cases
// where we have nested braced sections, which should be
// treated as individual members, like {a,{b,c},d}
function parseCommaParts(str) {
if (!str)
return [''];
var parts = [];
var m = balanced('{', '}', str);
if (!m)
return str.split(',');
var pre = m.pre;
var body = m.body;
var post = m.post;
var p = pre.split(',');
p[p.length-1] += '{' + body + '}';
var postParts = parseCommaParts(post);
if (post.length) {
p[p.length-1] += postParts.shift();
p.push.apply(p, postParts);
}
parts.push.apply(parts, p);
return parts;
}
function expandTop(str) {
if (!str)
return [];
return expand(escapeBraces(str), true).map(unescapeBraces);
}
function identity(e) {
return e;
}
function embrace(str) {
return '{' + str + '}';
}
function isPadded(el) {
return /^-?0\d/.test(el);
}
function lte(i, y) {
return i <= y;
}
function gte(i, y) {
return i >= y;
}
function expand(str, isTop) {
var expansions = [];
var m = balanced('{', '}', str);
if (!m || /\$$/.test(m.pre)) return [str];
var isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body);
var isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body);
var isSequence = isNumericSequence || isAlphaSequence;
var isOptions = /^(.*,)+(.+)?$/.test(m.body);
if (!isSequence && !isOptions) {
// {a},b}
if (m.post.match(/,.*}/)) {
str = m.pre + '{' + m.body + escClose + m.post;
return expand(str);
}
return [str];
}
var n;
if (isSequence) {
n = m.body.split(/\.\./);
} else {
n = parseCommaParts(m.body);
if (n.length === 1) {
// x{{a,b}}y ==> x{a}y x{b}y
n = expand(n[0], false).map(embrace);
if (n.length === 1) {
var post = m.post.length
? expand(m.post, false)
: [''];
return post.map(function(p) {
return m.pre + n[0] + p;
});
}
}
}
// at this point, n is the parts, and we know it's not a comma set
// with a single entry.
// no need to expand pre, since it is guaranteed to be free of brace-sets
var pre = m.pre;
var post = m.post.length
? expand(m.post, false)
: [''];
var N;
if (isSequence) {
var x = numeric(n[0]);
var y = numeric(n[1]);
var width = Math.max(n[0].length, n[1].length)
var incr = n.length == 3
? Math.abs(numeric(n[2]))
: 1;
var test = lte;
var reverse = y < x;
if (reverse) {
incr *= -1;
test = gte;
}
var pad = n.some(isPadded);
N = [];
for (var i = x; test(i, y); i += incr) {
var c;
if (isAlphaSequence) {
c = String.fromCharCode(i);
if (c === '\\')
c = '';
} else {
c = String(i);
if (pad) {
var need = width - c.length;
if (need > 0) {
var z = new Array(need + 1).join('0');
if (i < 0)
c = '-' + z + c.slice(1);
else
c = z + c;
}
}
}
N.push(c);
}
} else {
N = concatMap(n, function(el) { return expand(el, false) });
}
for (var j = 0; j < N.length; j++) {
for (var k = 0; k < post.length; k++) {
var expansion = pre + N[j] + post[k];
if (!isTop || isSequence || expansion)
expansions.push(expansion);
}
}
return expansions;
}
# balanced-match
Match balanced string pairs, like `{` and `}` or `<b>` and `</b>`.
[![build status](https://secure.travis-ci.org/juliangruber/balanced-match.svg)](http://travis-ci.org/juliangruber/balanced-match)
[![downloads](https://img.shields.io/npm/dm/balanced-match.svg)](https://www.npmjs.org/package/balanced-match)
[![testling badge](https://ci.testling.com/juliangruber/balanced-match.png)](https://ci.testling.com/juliangruber/balanced-match)
## Example
Get the first matching pair of braces:
```js
var balanced = require('balanced-match');
console.log(balanced('{', '}', 'pre{in{nested}}post'));
console.log(balanced('{', '}', 'pre{first}between{second}post'));
```
The matches are:
```bash
$ node example.js
{ start: 3, end: 14, pre: 'pre', body: 'in{nested}', post: 'post' }
{ start: 3,
end: 9,
pre: 'pre',
body: 'first',
post: 'between{second}post' }
```
## API
### var m = balanced(a, b, str)
For the first non-nested matching pair of `a` and `b` in `str`, return an
object with those keys:
* **start** the index of the first match of `a`
* **end** the index of the matching `b`
* **pre** the preamble, `a` and `b` not included
* **body** the match, `a` and `b` not included
* **post** the postscript, `a` and `b` not included
If there's no match, `undefined` will be returned.
If the `str` contains more `a` than `b` / there are unmatched pairs, the first match that was closed will be used. For example, `{{a}` will match `['{', 'a', '']`.
## Installation
With [npm](https://npmjs.org) do:
```bash
npm install balanced-match
```
## License
(MIT)
Copyright (c) 2013 Julian Gruber &lt;julian@juliangruber.com&gt;
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.
var balanced = require('./');
console.log(balanced('{', '}', 'pre{in{nested}}post'));
console.log(balanced('{', '}', 'pre{first}between{second}post'));
module.exports = balanced;
function balanced(a, b, str) {
var bal = 0;
var m = {};
var ended = false;
for (var i = 0; i < str.length; i++) {
if (a == str.substr(i, a.length)) {
if (!('start' in m)) m.start = i;
bal++;
}
else if (b == str.substr(i, b.length) && 'start' in m) {
ended = true;
bal--;
if (!bal) {
m.end = i;
m.pre = str.substr(0, m.start);
m.body = (m.end - m.start > 1)
? str.substring(m.start + a.length, m.end)
: '';
m.post = str.slice(m.end + b.length);
return m;
}
}
}
// if we opened more than we closed, find the one we closed
if (bal && ended) {
var start = m.start + a.length;
m = balanced(a, b, str.substr(start));
if (m) {
m.start += start;
m.end += start;
m.pre = str.slice(0, start) + m.pre;
}
return m;
}
}
{
"name": "balanced-match",
"description": "Match balanced character pairs, like \"{\" and \"}\"",
"version": "0.2.0",
"repository": {
"type": "git",
"url": "git://github.com/juliangruber/balanced-match.git"
},
"homepage": "https://github.com/juliangruber/balanced-match",
"main": "index.js",
"scripts": {
"test": "make test"
},
"dependencies": {},
"devDependencies": {
"tape": "~1.1.1"
},
"keywords": [
"match",
"regexp",
"test",
"balanced",
"parse"
],
"author": {
"name": "Julian Gruber",
"email": "mail@juliangruber.com",
"url": "http://juliangruber.com"
},
"license": "MIT",
"testling": {
"files": "test/*.js",
"browsers": [
"ie/8..latest",
"firefox/20..latest",
"firefox/nightly",
"chrome/25..latest",
"chrome/canary",
"opera/12..latest",
"opera/next",
"safari/5.1..latest",
"ipad/6.0..latest",
"iphone/6.0..latest",
"android-browser/4.2..latest"
]
},
"gitHead": "ba40ed78e7114a4a67c51da768a100184dead39c",
"bugs": {
"url": "https://github.com/juliangruber/balanced-match/issues"
},
"_id": "balanced-match@0.2.0",
"_shasum": "38f6730c03aab6d5edbb52bd934885e756d71674",
"_from": "balanced-match@>=0.2.0 <0.3.0",
"_npmVersion": "2.1.8",
"_nodeVersion": "0.10.32",
"_npmUser": {
"name": "juliangruber",
"email": "julian@juliangruber.com"
},
"maintainers": [
{
"name": "juliangruber",
"email": "julian@juliangruber.com"
}
],
"dist": {
"shasum": "38f6730c03aab6d5edbb52bd934885e756d71674",
"tarball": "http://registry.npmjs.org/balanced-match/-/balanced-match-0.2.0.tgz"
},
"directories": {},
"_resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.2.0.tgz",
"readme": "ERROR: No README data found!"
}
var test = require('tape');
var balanced = require('..');
test('balanced', function(t) {
t.deepEqual(balanced('{', '}', 'pre{in{nest}}post'), {
start: 3,
end: 12,
pre: 'pre',
body: 'in{nest}',
post: 'post'
});
t.deepEqual(balanced('{', '}', '{{{{{{{{{in}post'), {
start: 8,
end: 11,
pre: '{{{{{{{{',
body: 'in',
post: 'post'
});
t.deepEqual(balanced('{', '}', 'pre{body{in}post'), {
start: 8,
end: 11,
pre: 'pre{body',
body: 'in',
post: 'post'
});
t.deepEqual(balanced('{', '}', 'pre}{in{nest}}post'), {
start: 4,
end: 13,
pre: 'pre}',
body: 'in{nest}',
post: 'post'
});
t.deepEqual(balanced('{', '}', 'pre{body}between{body2}post'), {
start: 3,
end: 8,
pre: 'pre',
body: 'body',
post: 'between{body2}post'
});
t.notOk(balanced('{', '}', 'nope'), 'should be notOk');
t.deepEqual(balanced('<b>', '</b>', 'pre<b>in<b>nest</b></b>post'), {
start: 3,
end: 19,
pre: 'pre',
body: 'in<b>nest</b>',
post: 'post'
});
t.deepEqual(balanced('<b>', '</b>', 'pre</b><b>in<b>nest</b></b>post'), {
start: 7,
end: 23,
pre: 'pre</b>',
body: 'in<b>nest</b>',
post: 'post'
});
t.end();
});
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.
concat-map
==========
Concatenative mapdashery.
[![browser support](http://ci.testling.com/substack/node-concat-map.png)](http://ci.testling.com/substack/node-concat-map)
[![build status](https://secure.travis-ci.org/substack/node-concat-map.png)](http://travis-ci.org/substack/node-concat-map)
example
=======
``` js
var concatMap = require('concat-map');
var xs = [ 1, 2, 3, 4, 5, 6 ];
var ys = concatMap(xs, function (x) {
return x % 2 ? [ x - 0.1, x, x + 0.1 ] : [];
});
console.dir(ys);
```
***
```
[ 0.9, 1, 1.1, 2.9, 3, 3.1, 4.9, 5, 5.1 ]
```
methods
=======
``` js
var concatMap = require('concat-map')
```
concatMap(xs, fn)
-----------------
Return an array of concatenated elements by calling `fn(x, i)` for each element
`x` and each index `i` in the array `xs`.
When `fn(x, i)` returns an array, its result will be concatenated with the
result array. If `fn(x, i)` returns anything else, that value will be pushed
onto the end of the result array.
install
=======
With [npm](http://npmjs.org) do:
```
npm install concat-map
```
license
=======
MIT
notes
=====
This module was written while sitting high above the ground in a tree.
var concatMap = require('../');
var xs = [ 1, 2, 3, 4, 5, 6 ];
var ys = concatMap(xs, function (x) {
return x % 2 ? [ x - 0.1, x, x + 0.1 ] : [];
});
console.dir(ys);
module.exports = function (xs, fn) {
var res = [];
for (var i = 0; i < xs.length; i++) {
var x = fn(xs[i], i);
if (isArray(x)) res.push.apply(res, x);
else res.push(x);
}
return res;
};
var isArray = Array.isArray || function (xs) {
return Object.prototype.toString.call(xs) === '[object Array]';
};
{
"name": "concat-map",
"description": "concatenative mapdashery",
"version": "0.0.1",
"repository": {
"type": "git",
"url": "git://github.com/substack/node-concat-map.git"
},
"main": "index.js",
"keywords": [
"concat",
"concatMap",
"map",
"functional",
"higher-order"
],
"directories": {
"example": "example",
"test": "test"
},
"scripts": {
"test": "tape test/*.js"
},
"devDependencies": {
"tape": "~2.4.0"
},
"license": "MIT",
"author": {
"name": "James Halliday",
"email": "mail@substack.net",
"url": "http://substack.net"
},
"testling": {
"files": "test/*.js",
"browsers": {
"ie": [
6,
7,
8,
9
],
"ff": [
3.5,
10,
15
],
"chrome": [
10,
22
],
"safari": [
5.1
],
"opera": [
12
]
}
},
"bugs": {
"url": "https://github.com/substack/node-concat-map/issues"
},
"homepage": "https://github.com/substack/node-concat-map",
"_id": "concat-map@0.0.1",
"dist": {
"shasum": "d8a96bd77fd68df7793a73036a3ba0d5405d477b",
"tarball": "http://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz"
},
"_from": "concat-map@0.0.1",
"_npmVersion": "1.3.21",
"_npmUser": {
"name": "substack",
"email": "mail@substack.net"
},
"maintainers": [
{
"name": "substack",
"email": "mail@substack.net"
}
],
"_shasum": "d8a96bd77fd68df7793a73036a3ba0d5405d477b",
"_resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"readme": "ERROR: No README data found!"
}
var concatMap = require('../');
var test = require('tape');
test('empty or not', function (t) {
var xs = [ 1, 2, 3, 4, 5, 6 ];
var ixes = [];
var ys = concatMap(xs, function (x, ix) {
ixes.push(ix);
return x % 2 ? [ x - 0.1, x, x + 0.1 ] : [];
});
t.same(ys, [ 0.9, 1, 1.1, 2.9, 3, 3.1, 4.9, 5, 5.1 ]);
t.same(ixes, [ 0, 1, 2, 3, 4, 5 ]);
t.end();
});
test('always something', function (t) {
var xs = [ 'a', 'b', 'c', 'd' ];
var ys = concatMap(xs, function (x) {
return x === 'b' ? [ 'B', 'B', 'B' ] : [ x ];
});
t.same(ys, [ 'a', 'B', 'B', 'B', 'c', 'd' ]);
t.end();
});
test('scalars', function (t) {
var xs = [ 'a', 'b', 'c', 'd' ];
var ys = concatMap(xs, function (x) {
return x === 'b' ? [ 'B', 'B', 'B' ] : x;
});
t.same(ys, [ 'a', 'B', 'B', 'B', 'c', 'd' ]);
t.end();
});
test('undefs', function (t) {
var xs = [ 'a', 'b', 'c', 'd' ];
var ys = concatMap(xs, function () {});
t.same(ys, [ undefined, undefined, undefined, undefined ]);
t.end();
});
{
"name": "brace-expansion",
"description": "Brace expansion as known from sh/bash",
"version": "1.1.0",
"repository": {
"type": "git",
"url": "git://github.com/juliangruber/brace-expansion.git"
},
"homepage": "https://github.com/juliangruber/brace-expansion",
"main": "index.js",
"scripts": {
"test": "tape test/*.js",
"gentest": "bash test/generate.sh"
},
"dependencies": {
"balanced-match": "^0.2.0",
"concat-map": "0.0.1"
},
"devDependencies": {
"tape": "^3.0.3"
},
"keywords": [],
"author": {
"name": "Julian Gruber",
"email": "mail@juliangruber.com",
"url": "http://juliangruber.com"
},
"license": "MIT",
"testling": {
"files": "test/*.js",
"browsers": [
"ie/8..latest",
"firefox/20..latest",
"firefox/nightly",
"chrome/25..latest",
"chrome/canary",
"opera/12..latest",
"opera/next",
"safari/5.1..latest",
"ipad/6.0..latest",
"iphone/6.0..latest",
"android-browser/4.2..latest"
]
},
"gitHead": "b5fa3b1c74e5e2dba2d0efa19b28335641bc1164",
"bugs": {
"url": "https://github.com/juliangruber/brace-expansion/issues"
},
"_id": "brace-expansion@1.1.0",
"_shasum": "c9b7d03c03f37bc704be100e522b40db8f6cfcd9",
"_from": "brace-expansion@>=1.0.0 <2.0.0",
"_npmVersion": "2.1.10",
"_nodeVersion": "0.10.32",
"_npmUser": {
"name": "juliangruber",
"email": "julian@juliangruber.com"
},
"maintainers": [
{
"name": "juliangruber",
"email": "julian@juliangruber.com"
},
{
"name": "isaacs",
"email": "isaacs@npmjs.com"
}
],
"dist": {
"shasum": "c9b7d03c03f37bc704be100e522b40db8f6cfcd9",
"tarball": "http://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.0.tgz"
},
"directories": {},
"_resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.0.tgz",
"readme": "ERROR: No README data found!"
}
var test = require('tape');
var expand = require('..');
var fs = require('fs');
var resfile = __dirname + '/bash-results.txt';
var cases = fs.readFileSync(resfile, 'utf8').split('><><><><');
// throw away the EOF marker
cases.pop()
test('matches bash expansions', function(t) {
cases.forEach(function(testcase) {
var set = testcase.split('\n');
var pattern = set.shift();
var actual = expand(pattern);
// If it expands to the empty string, then it's actually
// just nothing, but Bash is a singly typed language, so
// "nothing" is the same as "".
if (set.length === 1 && set[0] === '') {
set = []
} else {
// otherwise, strip off the [] that were added so that
// "" expansions would be preserved properly.
set = set.map(function (s) {
return s.replace(/^\[|\]$/g, '')
})
}
t.same(actual, set, pattern);
});
t.end();
})
A{b,{d,e},{f,g}}Z
[AbZ]
[AdZ]
[AeZ]
[AfZ]
[AgZ]><><><><PRE-{a,b}{{a,b},a,b}-POST
[PRE-aa-POST]
[PRE-ab-POST]
[PRE-aa-POST]
[PRE-ab-POST]
[PRE-ba-POST]
[PRE-bb-POST]
[PRE-ba-POST]
[PRE-bb-POST]><><><><\{a,b}{{a,b},a,b}
[{a,b}a]
[{a,b}b]
[{a,b}a]
[{a,b}b]><><><><{{a,b}
[{a]
[{b]><><><><{a,b}}
[a}]
[b}]><><><><{,}
><><><><a{,}
[a]
[a]><><><><{,}b
[b]
[b]><><><><a{,}b
[ab]
[ab]><><><><a{b}c
[a{b}c]><><><><a{1..5}b
[a1b]
[a2b]
[a3b]
[a4b]
[a5b]><><><><a{01..5}b
[a01b]
[a02b]
[a03b]
[a04b]
[a05b]><><><><a{-01..5}b
[a-01b]
[a000b]
[a001b]
[a002b]
[a003b]
[a004b]
[a005b]><><><><a{-01..5..3}b
[a-01b]
[a002b]
[a005b]><><><><a{001..9}b
[a001b]
[a002b]
[a003b]
[a004b]
[a005b]
[a006b]
[a007b]
[a008b]
[a009b]><><><><a{b,c{d,e},{f,g}h}x{y,z
[abx{y,z]
[acdx{y,z]
[acex{y,z]
[afhx{y,z]
[aghx{y,z]><><><><a{b,c{d,e},{f,g}h}x{y,z\}
[abx{y,z}]
[acdx{y,z}]
[acex{y,z}]
[afhx{y,z}]
[aghx{y,z}]><><><><a{b,c{d,e},{f,g}h}x{y,z}
[abxy]
[abxz]
[acdxy]
[acdxz]
[acexy]
[acexz]
[afhxy]
[afhxz]
[aghxy]
[aghxz]><><><><a{b{c{d,e}f{x,y{{g}h
[a{b{cdf{x,y{{g}h]
[a{b{cef{x,y{{g}h]><><><><a{b{c{d,e}f{x,y{}g}h
[a{b{cdfxh]
[a{b{cdfy{}gh]
[a{b{cefxh]
[a{b{cefy{}gh]><><><><a{b{c{d,e}f{x,y}}g}h
[a{b{cdfx}g}h]
[a{b{cdfy}g}h]
[a{b{cefx}g}h]
[a{b{cefy}g}h]><><><><a{b{c{d,e}f}g}h
[a{b{cdf}g}h]
[a{b{cef}g}h]><><><><a{{x,y},z}b
[axb]
[ayb]
[azb]><><><><f{x,y{g,z}}h
[fxh]
[fygh]
[fyzh]><><><><f{x,y{{g,z}}h
[f{x,y{g}h]
[f{x,y{z}h]><><><><f{x,y{{g,z}}h}
[fx]
[fy{g}h]
[fy{z}h]><><><><f{x,y{{g}h
[f{x,y{{g}h]><><><><f{x,y{{g}}h
[f{x,y{{g}}h]><><><><f{x,y{}g}h
[fxh]
[fy{}gh]><><><><z{a,b{,c}d
[z{a,bd]
[z{a,bcd]><><><><z{a,b},c}d
[za,c}d]
[zb,c}d]><><><><{-01..5}
[-01]
[000]
[001]
[002]
[003]
[004]
[005]><><><><{-05..100..5}
[-05]
[000]
[005]
[010]
[015]
[020]
[025]
[030]
[035]
[040]
[045]
[050]
[055]
[060]
[065]
[070]
[075]
[080]
[085]
[090]
[095]
[100]><><><><{-05..100}
[-05]
[-04]
[-03]
[-02]
[-01]
[000]
[001]
[002]
[003]
[004]
[005]
[006]
[007]
[008]
[009]
[010]
[011]
[012]
[013]
[014]
[015]
[016]
[017]
[018]
[019]
[020]
[021]
[022]
[023]
[024]
[025]
[026]
[027]
[028]
[029]
[030]
[031]
[032]
[033]
[034]
[035]
[036]
[037]
[038]
[039]
[040]
[041]
[042]
[043]
[044]
[045]
[046]
[047]
[048]
[049]
[050]
[051]
[052]
[053]
[054]
[055]
[056]
[057]
[058]
[059]
[060]
[061]
[062]
[063]
[064]
[065]
[066]
[067]
[068]
[069]
[070]
[071]
[072]
[073]
[074]
[075]
[076]
[077]
[078]
[079]
[080]
[081]
[082]
[083]
[084]
[085]
[086]
[087]
[088]
[089]
[090]
[091]
[092]
[093]
[094]
[095]
[096]
[097]
[098]
[099]
[100]><><><><{0..5..2}
[0]
[2]
[4]><><><><{0001..05..2}
[0001]
[0003]
[0005]><><><><{0001..-5..2}
[0001]
[-001]
[-003]
[-005]><><><><{0001..-5..-2}
[0001]
[-001]
[-003]
[-005]><><><><{0001..5..-2}
[0001]
[0003]
[0005]><><><><{01..5}
[01]
[02]
[03]
[04]
[05]><><><><{1..05}
[01]
[02]
[03]
[04]
[05]><><><><{1..05..3}
[01]
[04]><><><><{05..100}
[005]
[006]
[007]
[008]
[009]
[010]
[011]
[012]
[013]
[014]
[015]
[016]
[017]
[018]
[019]
[020]
[021]
[022]
[023]
[024]
[025]
[026]
[027]
[028]
[029]
[030]
[031]
[032]
[033]
[034]
[035]
[036]
[037]
[038]
[039]
[040]
[041]
[042]
[043]
[044]
[045]
[046]
[047]
[048]
[049]
[050]
[051]
[052]
[053]
[054]
[055]
[056]
[057]
[058]
[059]
[060]
[061]
[062]
[063]
[064]
[065]
[066]
[067]
[068]
[069]
[070]
[071]
[072]
[073]
[074]
[075]
[076]
[077]
[078]
[079]
[080]
[081]
[082]
[083]
[084]
[085]
[086]
[087]
[088]
[089]
[090]
[091]
[092]
[093]
[094]
[095]
[096]
[097]
[098]
[099]
[100]><><><><{0a..0z}
[{0a..0z}]><><><><{a,b\}c,d}
[a]
[b}c]
[d]><><><><{a,b{c,d}
[{a,bc]
[{a,bd]><><><><{a,b}c,d}
[ac,d}]
[bc,d}]><><><><{a..F}
[a]
[`]
[_]
[^]
[]]
[]
[[]
[Z]
[Y]
[X]
[W]
[V]
[U]
[T]
[S]
[R]
[Q]
[P]
[O]
[N]
[M]
[L]
[K]
[J]
[I]
[H]
[G]
[F]><><><><{A..f}
[A]
[B]
[C]
[D]
[E]
[F]
[G]
[H]
[I]
[J]
[K]
[L]
[M]
[N]
[O]
[P]
[Q]
[R]
[S]
[T]
[U]
[V]
[W]
[X]
[Y]
[Z]
[[]
[]
[]]
[^]
[_]
[`]
[a]
[b]
[c]
[d]
[e]
[f]><><><><{a..Z}
[a]
[`]
[_]
[^]
[]]
[]
[[]
[Z]><><><><{A..z}
[A]
[B]
[C]
[D]
[E]
[F]
[G]
[H]
[I]
[J]
[K]
[L]
[M]
[N]
[O]
[P]
[Q]
[R]
[S]
[T]
[U]
[V]
[W]
[X]
[Y]
[Z]
[[]
[]
[]]
[^]
[_]
[`]
[a]
[b]
[c]
[d]
[e]
[f]
[g]
[h]
[i]
[j]
[k]
[l]
[m]
[n]
[o]
[p]
[q]
[r]
[s]
[t]
[u]
[v]
[w]
[x]
[y]
[z]><><><><{z..A}
[z]
[y]
[x]
[w]
[v]
[u]
[t]
[s]
[r]
[q]
[p]
[o]
[n]
[m]
[l]
[k]
[j]
[i]
[h]
[g]
[f]
[e]
[d]
[c]
[b]
[a]
[`]
[_]
[^]
[]]
[]
[[]
[Z]
[Y]
[X]
[W]
[V]
[U]
[T]
[S]
[R]
[Q]
[P]
[O]
[N]
[M]
[L]
[K]
[J]
[I]
[H]
[G]
[F]
[E]
[D]
[C]
[B]
[A]><><><><{Z..a}
[Z]
[[]
[]
[]]
[^]
[_]
[`]
[a]><><><><{a..F..2}
[a]
[_]
[]]
[[]
[Y]
[W]
[U]
[S]
[Q]
[O]
[M]
[K]
[I]
[G]><><><><{A..f..02}
[A]
[C]
[E]
[G]
[I]
[K]
[M]
[O]
[Q]
[S]
[U]
[W]
[Y]
[[]
[]]
[_]
[a]
[c]
[e]><><><><{a..Z..5}
[a]
[]><><><><d{a..Z..5}b
[dab]
[db]><><><><{A..z..10}
[A]
[K]
[U]
[_]
[i]
[s]><><><><{z..A..-2}
[z]
[x]
[v]
[t]
[r]
[p]
[n]
[l]
[j]
[h]
[f]
[d]
[b]
[`]
[^]
[]
[Z]
[X]
[V]
[T]
[R]
[P]
[N]
[L]
[J]
[H]
[F]
[D]
[B]><><><><{Z..a..20}
[Z]><><><><{a{,b}
[{a]
[{ab]><><><><{a},b}
[a}]
[b]><><><><{x,y{,}g}
[x]
[yg]
[yg]><><><><{x,y{}g}
[x]
[y{}g]><><><><{{a,b}
[{a]
[{b]><><><><{{a,b},c}
[a]
[b]
[c]><><><><{{a,b}c}
[{ac}]
[{bc}]><><><><{{a,b},}
[a]
[b]><><><><X{{a,b},}X
[XaX]
[XbX]
[XX]><><><><{{a,b},}c
[ac]
[bc]
[c]><><><><{{a,b}.}
[{a.}]
[{b.}]><><><><{{a,b}}
[{a}]
[{b}]><><><><X{a..#}X
[X{a..#}X]><><><><
><><><><{-10..00}
[-10]
[-09]
[-08]
[-07]
[-06]
[-05]
[-04]
[-03]
[-02]
[-01]
[000]><><><><{a,\\{a,b}c}
[a]
[\ac]
[\bc]><><><><{a,\{a,b}c}
[ac}]
[{ac}]
[bc}]><><><><a,\{b,c}
[a,{b,c}]><><><><{-10.\.00}
[{-10..00}]><><><><ff{c,b,a}
[ffc]
[ffb]
[ffa]><><><><f{d,e,f}g
[fdg]
[feg]
[ffg]><><><><{l,n,m}xyz
[lxyz]
[nxyz]
[mxyz]><><><><{abc\,def}
[{abc,def}]><><><><{abc}
[{abc}]><><><><{x\,y,\{abc\},trie}
[x,y]
[{abc}]
[trie]><><><><{}
[{}]><><><><}
[}]><><><><{
[{]><><><><abcd{efgh
[abcd{efgh]><><><><{1..10}
[1]
[2]
[3]
[4]
[5]
[6]
[7]
[8]
[9]
[10]><><><><{0..10,braces}
[0..10]
[braces]><><><><{{0..10},braces}
[0]
[1]
[2]
[3]
[4]
[5]
[6]
[7]
[8]
[9]
[10]
[braces]><><><><x{{0..10},braces}y
[x0y]
[x1y]
[x2y]
[x3y]
[x4y]
[x5y]
[x6y]
[x7y]
[x8y]
[x9y]
[x10y]
[xbracesy]><><><><{3..3}
[3]><><><><x{3..3}y
[x3y]><><><><{10..1}
[10]
[9]
[8]
[7]
[6]
[5]
[4]
[3]
[2]
[1]><><><><{10..1}y
[10y]
[9y]
[8y]
[7y]
[6y]
[5y]
[4y]
[3y]
[2y]
[1y]><><><><x{10..1}y
[x10y]
[x9y]
[x8y]
[x7y]
[x6y]
[x5y]
[x4y]
[x3y]
[x2y]
[x1y]><><><><{a..f}
[a]
[b]
[c]
[d]
[e]
[f]><><><><{f..a}
[f]
[e]
[d]
[c]
[b]
[a]><><><><{a..A}
[a]
[`]
[_]
[^]
[]]
[]
[[]
[Z]
[Y]
[X]
[W]
[V]
[U]
[T]
[S]
[R]
[Q]
[P]
[O]
[N]
[M]
[L]
[K]
[J]
[I]
[H]
[G]
[F]
[E]
[D]
[C]
[B]
[A]><><><><{A..a}
[A]
[B]
[C]
[D]
[E]
[F]
[G]
[H]
[I]
[J]
[K]
[L]
[M]
[N]
[O]
[P]
[Q]
[R]
[S]
[T]
[U]
[V]
[W]
[X]
[Y]
[Z]
[[]
[]
[]]
[^]
[_]
[`]
[a]><><><><{f..f}
[f]><><><><{1..f}
[{1..f}]><><><><{f..1}
[{f..1}]><><><><{-1..-10}
[-1]
[-2]
[-3]
[-4]
[-5]
[-6]
[-7]
[-8]
[-9]
[-10]><><><><{-20..0}
[-20]
[-19]
[-18]
[-17]
[-16]
[-15]
[-14]
[-13]
[-12]
[-11]
[-10]
[-9]
[-8]
[-7]
[-6]
[-5]
[-4]
[-3]
[-2]
[-1]
[0]><><><><a-{b{d,e}}-c
[a-{bd}-c]
[a-{be}-c]><><><><a-{bdef-{g,i}-c
[a-{bdef-g-c]
[a-{bdef-i-c]><><><><{klklkl}{1,2,3}
[{klklkl}1]
[{klklkl}2]
[{klklkl}3]><><><><{1..10..2}
[1]
[3]
[5]
[7]
[9]><><><><{-1..-10..2}
[-1]
[-3]
[-5]
[-7]
[-9]><><><><{-1..-10..-2}
[-1]
[-3]
[-5]
[-7]
[-9]><><><><{10..1..-2}
[10]
[8]
[6]
[4]
[2]><><><><{10..1..2}
[10]
[8]
[6]
[4]
[2]><><><><{1..20..2}
[1]
[3]
[5]
[7]
[9]
[11]
[13]
[15]
[17]
[19]><><><><{1..20..20}
[1]><><><><{100..0..5}
[100]
[95]
[90]
[85]
[80]
[75]
[70]
[65]
[60]
[55]
[50]
[45]
[40]
[35]
[30]
[25]
[20]
[15]
[10]
[5]
[0]><><><><{100..0..-5}
[100]
[95]
[90]
[85]
[80]
[75]
[70]
[65]
[60]
[55]
[50]
[45]
[40]
[35]
[30]
[25]
[20]
[15]
[10]
[5]
[0]><><><><{a..z}
[a]
[b]
[c]
[d]
[e]
[f]
[g]
[h]
[i]
[j]
[k]
[l]
[m]
[n]
[o]
[p]
[q]
[r]
[s]
[t]
[u]
[v]
[w]
[x]
[y]
[z]><><><><{a..z..2}
[a]
[c]
[e]
[g]
[i]
[k]
[m]
[o]
[q]
[s]
[u]
[w]
[y]><><><><{z..a..-2}
[z]
[x]
[v]
[t]
[r]
[p]
[n]
[l]
[j]
[h]
[f]
[d]
[b]><><><><{2147483645..2147483649}
[2147483645]
[2147483646]
[2147483647]
[2147483648]
[2147483649]><><><><{10..0..2}
[10]
[8]
[6]
[4]
[2]
[0]><><><><{10..0..-2}
[10]
[8]
[6]
[4]
[2]
[0]><><><><{-50..-0..5}
[-50]
[-45]
[-40]
[-35]
[-30]
[-25]
[-20]
[-15]
[-10]
[-5]
[0]><><><><{1..10.f}
[{1..10.f}]><><><><{1..ff}
[{1..ff}]><><><><{1..10..ff}
[{1..10..ff}]><><><><{1.20..2}
[{1.20..2}]><><><><{1..20..f2}
[{1..20..f2}]><><><><{1..20..2f}
[{1..20..2f}]><><><><{1..2f..2}
[{1..2f..2}]><><><><{1..ff..2}
[{1..ff..2}]><><><><{1..ff}
[{1..ff}]><><><><{1..f}
[{1..f}]><><><><{1..0f}
[{1..0f}]><><><><{1..10f}
[{1..10f}]><><><><{1..10.f}
[{1..10.f}]><><><><{1..10.f}
[{1..10.f}]><><><><
\ No newline at end of file
# skip quotes for now
# "{x,x}"
# {"x,x"}
# {x","x}
# '{a,b}{{a,b},a,b}'
A{b,{d,e},{f,g}}Z
PRE-{a,b}{{a,b},a,b}-POST
\\{a,b}{{a,b},a,b}
{{a,b}
{a,b}}
{,}
a{,}
{,}b
a{,}b
a{b}c
a{1..5}b
a{01..5}b
a{-01..5}b
a{-01..5..3}b
a{001..9}b
a{b,c{d,e},{f,g}h}x{y,z
a{b,c{d,e},{f,g}h}x{y,z\\}
a{b,c{d,e},{f,g}h}x{y,z}
a{b{c{d,e}f{x,y{{g}h
a{b{c{d,e}f{x,y{}g}h
a{b{c{d,e}f{x,y}}g}h
a{b{c{d,e}f}g}h
a{{x,y},z}b
f{x,y{g,z}}h
f{x,y{{g,z}}h
f{x,y{{g,z}}h}
f{x,y{{g}h
f{x,y{{g}}h
f{x,y{}g}h
z{a,b{,c}d
z{a,b},c}d
{-01..5}
{-05..100..5}
{-05..100}
{0..5..2}
{0001..05..2}
{0001..-5..2}
{0001..-5..-2}
{0001..5..-2}
{01..5}
{1..05}
{1..05..3}
{05..100}
{0a..0z}
{a,b\\}c,d}
{a,b{c,d}
{a,b}c,d}
{a..F}
{A..f}
{a..Z}
{A..z}
{z..A}
{Z..a}
{a..F..2}
{A..f..02}
{a..Z..5}
d{a..Z..5}b
{A..z..10}
{z..A..-2}
{Z..a..20}
{a{,b}
{a},b}
{x,y{,}g}
{x,y{}g}
{{a,b}
{{a,b},c}
{{a,b}c}
{{a,b},}
X{{a,b},}X
{{a,b},}c
{{a,b}.}
{{a,b}}
X{a..#}X
# this next one is an empty string
{-10..00}
# Need to escape slashes in here for reasons i guess.
{a,\\\\{a,b}c}
{a,\\{a,b}c}
a,\\{b,c}
{-10.\\.00}
#### bash tests/braces.tests
# Note that some tests are edited out because some features of
# bash are intentionally not supported in this brace expander.
ff{c,b,a}
f{d,e,f}g
{l,n,m}xyz
{abc\\,def}
{abc}
{x\\,y,\\{abc\\},trie}
# not impementing back-ticks obviously
# XXXX\\{`echo a b c | tr ' ' ','`\\}
{}
# We only ever have to worry about parsing a single argument,
# not a command line, so spaces have a different meaning than bash.
# { }
}
{
abcd{efgh
# spaces
# foo {1,2} bar
# not impementing back-ticks obviously
# `zecho foo {1,2} bar`
# $(zecho foo {1,2} bar)
# ${var} is not a variable here, like it is in bash. omit.
# foo{bar,${var}.}
# foo{bar,${var}}
# isaacs: skip quotes for now
# "${var}"{x,y}
# $var{x,y}
# ${var}{x,y}
# new sequence brace operators
{1..10}
# this doesn't work yet
{0..10,braces}
# but this does
{{0..10},braces}
x{{0..10},braces}y
{3..3}
x{3..3}y
{10..1}
{10..1}y
x{10..1}y
{a..f}
{f..a}
{a..A}
{A..a}
{f..f}
# mixes are incorrectly-formed brace expansions
{1..f}
{f..1}
# spaces
# 0{1..9} {10..20}
# do negative numbers work?
{-1..-10}
{-20..0}
# weirdly-formed brace expansions -- fixed in post-bash-3.1
a-{b{d,e}}-c
a-{bdef-{g,i}-c
# isaacs: skip quotes for now
# {"klklkl"}{1,2,3}
# isaacs: this is a valid test, though
{klklkl}{1,2,3}
# {"x,x"}
{1..10..2}
{-1..-10..2}
{-1..-10..-2}
{10..1..-2}
{10..1..2}
{1..20..2}
{1..20..20}
{100..0..5}
{100..0..-5}
{a..z}
{a..z..2}
{z..a..-2}
# make sure brace expansion handles ints > 2**31 - 1 using intmax_t
{2147483645..2147483649}
# unwanted zero-padding -- fixed post-bash-4.0
{10..0..2}
{10..0..-2}
{-50..-0..5}
# bad
{1..10.f}
{1..ff}
{1..10..ff}
{1.20..2}
{1..20..f2}
{1..20..2f}
{1..2f..2}
{1..ff..2}
{1..ff}
{1..f}
{1..0f}
{1..10f}
{1..10.f}
{1..10.f}
var test = require('tape');
var expand = require('..');
test('ignores ${', function(t) {
t.deepEqual(expand('${1..3}'), ['${1..3}']);
t.deepEqual(expand('${a,b}${c,d}'), ['${a,b}${c,d}']);
t.deepEqual(expand('x${a,b}x${c,d}x'), ['x${a,b}x${c,d}x']);
t.end();
});
var test = require('tape');
var expand = require('..');
test('empty option', function(t) {
t.deepEqual(expand('-v{,,,,}'), [
'-v', '-v', '-v', '-v', '-v'
]);
t.end();
});
#!/usr/bin/env bash
set -e
# Bash 4.3 because of arbitrary need to pick a single standard.
if [ "${BASH_VERSINFO[0]}" != "4" ] || [ "${BASH_VERSINFO[1]}" != "3" ]; then
echo "this script requires bash 4.3" >&2
exit 1
fi
CDPATH= cd "$(dirname "$0")"
js='require("./")(process.argv[1]).join(" ")'
cat cases.txt | \
while read case; do
if [ "${case:0:1}" = "#" ]; then
continue;
fi;
b="$($BASH -c 'for c in '"$case"'; do echo ["$c"]; done')"
echo "$case"
echo -n "$b><><><><";
done > bash-results.txt
var test = require('tape');
var expand = require('..');
test('negative increment', function(t) {
t.deepEqual(expand('{3..1}'), ['3', '2', '1']);
t.deepEqual(expand('{10..8}'), ['10', '9', '8']);
t.deepEqual(expand('{10..08}'), ['10', '09', '08']);
t.deepEqual(expand('{c..a}'), ['c', 'b', 'a']);
t.deepEqual(expand('{4..0..2}'), ['4', '2', '0']);
t.deepEqual(expand('{4..0..-2}'), ['4', '2', '0']);
t.deepEqual(expand('{e..a..2}'), ['e', 'c', 'a']);
t.end();
});
var test = require('tape');
var expand = require('..');
test('nested', function(t) {
t.deepEqual(expand('{a,b{1..3},c}'), [
'a', 'b1', 'b2', 'b3', 'c'
]);
t.deepEqual(expand('{{A..Z},{a..z}}'),
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('')
);
t.deepEqual(expand('ppp{,config,oe{,conf}}'), [
'ppp', 'pppconfig', 'pppoe', 'pppoeconf'
]);
t.end();
});
var test = require('tape');
var expand = require('..');
test('order', function(t) {
t.deepEqual(expand('a{d,c,b}e'), [
'ade', 'ace', 'abe'
]);
t.end();
});
var test = require('tape');
var expand = require('..');
test('pad', function(t) {
t.deepEqual(expand('{9..11}'), [
'9', '10', '11'
]);
t.deepEqual(expand('{09..11}'), [
'09', '10', '11'
]);
t.end();
});
var test = require('tape');
var expand = require('..');
test('x and y of same type', function(t) {
t.deepEqual(expand('{a..9}'), ['{a..9}']);
t.end();
});
var test = require('tape');
var expand = require('..');
test('numeric sequences', function(t) {
t.deepEqual(expand('a{1..2}b{2..3}c'), [
'a1b2c', 'a1b3c', 'a2b2c', 'a2b3c'
]);
t.deepEqual(expand('{1..2}{2..3}'), [
'12', '13', '22', '23'
]);
t.end();
});
test('numeric sequences with step count', function(t) {
t.deepEqual(expand('{0..8..2}'), [
'0', '2', '4', '6', '8'
]);
t.deepEqual(expand('{1..8..2}'), [
'1', '3', '5', '7'
]);
t.end();
});
test('numeric sequence with negative x / y', function(t) {
t.deepEqual(expand('{3..-2}'), [
'3', '2', '1', '0', '-1', '-2'
]);
t.end();
});
test('alphabetic sequences', function(t) {
t.deepEqual(expand('1{a..b}2{b..c}3'), [
'1a2b3', '1a2c3', '1b2b3', '1b2c3'
]);
t.deepEqual(expand('{a..b}{b..c}'), [
'ab', 'ac', 'bb', 'bc'
]);
t.end();
});
test('alphabetic sequences with step count', function(t) {
t.deepEqual(expand('{a..k..2}'), [
'a', 'c', 'e', 'g', 'i', 'k'
]);
t.deepEqual(expand('{b..k..2}'), [
'b', 'd', 'f', 'h', 'j'
]);
t.end();
});
{
"author": {
"name": "Isaac Z. Schlueter",
"email": "i@izs.me",
"url": "http://blog.izs.me"
},
"name": "minimatch",
"description": "a glob matcher in javascript",
"version": "2.0.8",
"repository": {
"type": "git",
"url": "git://github.com/isaacs/minimatch.git"
},
"main": "minimatch.js",
"scripts": {
"pretest": "standard minimatch.js test/*.js",
"test": "tap test/*.js",
"prepublish": "browserify -o browser.js -e minimatch.js --bare"
},
"engines": {
"node": "*"
},
"dependencies": {
"brace-expansion": "^1.0.0"
},
"devDependencies": {
"browserify": "^9.0.3",
"standard": "^3.7.2",
"tap": ""
},
"license": "ISC",
"files": [
"minimatch.js",
"browser.js"
],
"gitHead": "0bc7d9c4b2bc816502184862b45bd090de3406a3",
"bugs": {
"url": "https://github.com/isaacs/minimatch/issues"
},
"homepage": "https://github.com/isaacs/minimatch#readme",
"_id": "minimatch@2.0.8",
"_shasum": "0bc20f6bf3570a698ef0ddff902063c6cabda6bf",
"_from": "minimatch@>=2.0.1 <3.0.0",
"_npmVersion": "2.10.0",
"_nodeVersion": "2.0.1",
"_npmUser": {
"name": "isaacs",
"email": "isaacs@npmjs.com"
},
"dist": {
"shasum": "0bc20f6bf3570a698ef0ddff902063c6cabda6bf",
"tarball": "http://registry.npmjs.org/minimatch/-/minimatch-2.0.8.tgz"
},
"maintainers": [
{
"name": "isaacs",
"email": "i@izs.me"
}
],
"directories": {},
"_resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.8.tgz",
"readme": "ERROR: No README data found!"
}
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.
# once
Only call a function once.
## usage
```javascript
var once = require('once')
function load (file, cb) {
cb = once(cb)
loader.load('file')
loader.once('load', cb)
loader.once('error', cb)
}
```
Or add to the Function.prototype in a responsible way:
```javascript
// only has to be done once
require('once').proto()
function load (file, cb) {
cb = cb.once()
loader.load('file')
loader.once('load', cb)
loader.once('error', cb)
}
```
Ironically, the prototype feature makes this module twice as
complicated as necessary.
To check whether you function has been called, use `fn.called`. Once the
function is called for the first time the return value of the original
function is saved in `fn.value` and subsequent calls will continue to
return this value.
```javascript
var once = require('once')
function load (cb) {
cb = once(cb)
var stream = createStream()
stream.once('data', cb)
stream.once('end', function () {
if (!cb.called) cb(new Error('not found'))
})
}
```
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.
# wrappy
Callback wrapping utility
## USAGE
```javascript
var wrappy = require("wrappy")
// var wrapper = wrappy(wrapperFunction)
// make sure a cb is called only once
// See also: http://npm.im/once for this specific use case
var once = wrappy(function (cb) {
var called = false
return function () {
if (called) return
called = true
return cb.apply(this, arguments)
}
})
function printBoo () {
console.log('boo')
}
// has some rando property
printBoo.iAmBooPrinter = true
var onlyPrintOnce = once(printBoo)
onlyPrintOnce() // prints 'boo'
onlyPrintOnce() // does nothing
// random property is retained!
assert.equal(onlyPrintOnce.iAmBooPrinter, true)
```
{
"name": "wrappy",
"version": "1.0.1",
"description": "Callback wrapping utility",
"main": "wrappy.js",
"directories": {
"test": "test"
},
"dependencies": {},
"devDependencies": {
"tap": "^0.4.12"
},
"scripts": {
"test": "tap test/*.js"
},
"repository": {
"type": "git",
"url": "https://github.com/npm/wrappy"
},
"author": {
"name": "Isaac Z. Schlueter",
"email": "i@izs.me",
"url": "http://blog.izs.me/"
},
"license": "ISC",
"bugs": {
"url": "https://github.com/npm/wrappy/issues"
},
"homepage": "https://github.com/npm/wrappy",
"readme": "# wrappy\n\nCallback wrapping utility\n\n## USAGE\n\n```javascript\nvar wrappy = require(\"wrappy\")\n\n// var wrapper = wrappy(wrapperFunction)\n\n// make sure a cb is called only once\n// See also: http://npm.im/once for this specific use case\nvar once = wrappy(function (cb) {\n var called = false\n return function () {\n if (called) return\n called = true\n return cb.apply(this, arguments)\n }\n})\n\nfunction printBoo () {\n console.log('boo')\n}\n// has some rando property\nprintBoo.iAmBooPrinter = true\n\nvar onlyPrintOnce = once(printBoo)\n\nonlyPrintOnce() // prints 'boo'\nonlyPrintOnce() // does nothing\n\n// random property is retained!\nassert.equal(onlyPrintOnce.iAmBooPrinter, true)\n```\n",
"readmeFilename": "README.md",
"_id": "wrappy@1.0.1",
"_shasum": "1e65969965ccbc2db4548c6b84a6f2c5aedd4739",
"_resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz",
"_from": "wrappy@>=1.0.0 <2.0.0"
}
var test = require('tap').test
var wrappy = require('../wrappy.js')
test('basic', function (t) {
function onceifier (cb) {
var called = false
return function () {
if (called) return
called = true
return cb.apply(this, arguments)
}
}
onceifier.iAmOnce = {}
var once = wrappy(onceifier)
t.equal(once.iAmOnce, onceifier.iAmOnce)
var called = 0
function boo () {
t.equal(called, 0)
called++
}
// has some rando property
boo.iAmBoo = true
var onlyPrintOnce = once(boo)
onlyPrintOnce() // prints 'boo'
onlyPrintOnce() // does nothing
t.equal(called, 1)
// random property is retained!
t.equal(onlyPrintOnce.iAmBoo, true)
var logs = []
var logwrap = wrappy(function (msg, cb) {
logs.push(msg + ' wrapping cb')
return function () {
logs.push(msg + ' before cb')
var ret = cb.apply(this, arguments)
logs.push(msg + ' after cb')
}
})
var c = logwrap('foo', function () {
t.same(logs, [ 'foo wrapping cb', 'foo before cb' ])
})
c()
t.same(logs, [ 'foo wrapping cb', 'foo before cb', 'foo after cb' ])
t.end()
})
// Returns a wrapper function that returns a wrapped callback
// The wrapper function should do some stuff, and return a
// presumably different callback function.
// This makes sure that own properties are retained, so that
// decorations and such are not lost along the way.
module.exports = wrappy
function wrappy (fn, cb) {
if (fn && cb) return wrappy(fn)(cb)
if (typeof fn !== 'function')
throw new TypeError('need wrapper function')
Object.keys(fn).forEach(function (k) {
wrapper[k] = fn[k]
})
return wrapper
function wrapper() {
var args = new Array(arguments.length)
for (var i = 0; i < args.length; i++) {
args[i] = arguments[i]
}
var ret = fn.apply(this, args)
var cb = args[args.length-1]
if (typeof ret === 'function' && ret !== cb) {
Object.keys(cb).forEach(function (k) {
ret[k] = cb[k]
})
}
return ret
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment