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,10 +5,14 @@
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
0ECEF97594F04776B7BE0C66 /* Toast+UIView.m in Sources */ = {isa = PBXBuildFile; fileRef = 1DE50EBD09D2455DBC5D351E /* Toast+UIView.m */; };
1C584EB51F3C426D8A25DAAF /* AppDelegate+APPRegisterUserNotificationSettings.m in Sources */ = {isa = PBXBuildFile; fileRef = D5869E30F00647C1A2399FAC /* AppDelegate+APPRegisterUserNotificationSettings.m */; };
1D3623260D0F684500981E51 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D3623250D0F684500981E51 /* AppDelegate.m */; };
1D60589B0D05DD56006BFB54 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; };
288765FD0DF74451002DB57D /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765FC0DF74451002DB57D /* CoreGraphics.framework */; };
297157BA33654D9294C2E907 /* UILocalNotification+APPLocalNotification.m in Sources */ = {isa = PBXBuildFile; fileRef = 0EABFA908C98474CA4F6C65A /* UILocalNotification+APPLocalNotification.m */; };
301BF552109A68D80062928A /* libCordova.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 301BF535109A57CC0062928A /* libCordova.a */; };
302D95F114D2391D003F00A1 /* MainViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 302D95EF14D2391D003F00A1 /* MainViewController.m */; };
302D95F214D2391D003F00A1 /* MainViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 302D95F014D2391D003F00A1 /* MainViewController.xib */; };
......@@ -38,15 +42,13 @@
7E7966E51810823500FA85AD /* icon-76@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 7E7966DB1810823500FA85AD /* icon-76@2x.png */; };
7E7966E61810823500FA85AD /* icon-small.png in Resources */ = {isa = PBXBuildFile; fileRef = 7E7966DC1810823500FA85AD /* icon-small.png */; };
7E7966E71810823500FA85AD /* icon-small@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 7E7966DD1810823500FA85AD /* icon-small@2x.png */; };
9149ECD9BBCA4D8E9134ABC1 /* Toast.m in Sources */ = {isa = PBXBuildFile; fileRef = 358531870FE9418D801CA17D /* Toast.m */; };
AD36A476BF534005AC4468ED /* APPLocalNotification.m in Sources */ = {isa = PBXBuildFile; fileRef = 754762A7EDBD428EAA6B1370 /* APPLocalNotification.m */; };
AF44493D8C1E426D98DF16EF /* UIApplication+APPLocalNotification.m in Sources */ = {isa = PBXBuildFile; fileRef = 2F66F04C3AA942779C1C4F95 /* UIApplication+APPLocalNotification.m */; };
CC26E958D783460CB096D087 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 97129848CDCC42118CF1C40D /* QuartzCore.framework */; };
D4A0D8761607E02300AEF8BB /* Default-568h@2x~iphone.png in Resources */ = {isa = PBXBuildFile; fileRef = D4A0D8751607E02300AEF8BB /* Default-568h@2x~iphone.png */; };
6B489B4BC70B42A1A1ED596C /* Toast+UIView.m in Sources */ = {isa = PBXBuildFile; fileRef = 49A41E49185E401B9D6E65C6 /* Toast+UIView.m */; };
380ACB2600604A63A2DB79FF /* Toast.m in Sources */ = {isa = PBXBuildFile; fileRef = 24E7095CA0544A92B37F596F /* Toast.m */; };
35024486F61C43DEBCE510AD /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5D3ECFAF1EDE404BA6652960 /* QuartzCore.framework */; };
87985801CA7141F2ABDFA26C /* CDVDevice.m in Sources */ = {isa = PBXBuildFile; fileRef = 23D17A20B14445CB8E1A008A /* CDVDevice.m */; };
BCD48564514D4772B2A4B8A9 /* APPLocalNotification.m in Sources */ = {isa = PBXBuildFile; fileRef = 979507619BA5418E88EFC889 /* APPLocalNotification.m */; };
1D15D09292314FE1B88509DA /* APPLocalNotificationOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = ADF52FF21A8D45B19B24BCDA /* APPLocalNotificationOptions.m */; };
8821D32BBC744C43AA03747E /* UIApplication+APPLocalNotification.m in Sources */ = {isa = PBXBuildFile; fileRef = 929D5875A2EE490BAFAC25C3 /* UIApplication+APPLocalNotification.m */; };
69435A24D7CD463EBA565B60 /* UILocalNotification+APPLocalNotification.m in Sources */ = {isa = PBXBuildFile; fileRef = 632B9B22D7494695ACFAA5AF /* UILocalNotification+APPLocalNotification.m */; };
E2C8C56228EF4650921A8C13 /* CDVDevice.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D377024246144729DE8F96F /* CDVDevice.m */; };
EFFF31CCFEC944568CED9AF2 /* APPLocalNotificationOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D318D53B4C1444BAAA6DAF1 /* APPLocalNotificationOptions.m */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
......@@ -67,13 +69,14 @@
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
0EABFA908C98474CA4F6C65A /* UILocalNotification+APPLocalNotification.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "UILocalNotification+APPLocalNotification.m"; path = "de.appplant.cordova.plugin.local-notification/UILocalNotification+APPLocalNotification.m"; sourceTree = "<group>"; };
1D3623240D0F684500981E51 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
1D3623250D0F684500981E51 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
1D6058910D05DD3D006BFB54 /* NotificationExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "NotificationExample.app"; sourceTree = BUILT_PRODUCTS_DIR; };
1F766FDD13BBADB100FB74C0 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = Localizable.strings; sourceTree = "<group>"; };
1F766FE013BBADB100FB74C0 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = Localizable.strings; sourceTree = "<group>"; };
1D6058910D05DD3D006BFB54 /* NotificationExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = NotificationExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
1DE50EBD09D2455DBC5D351E /* Toast+UIView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "Toast+UIView.m"; path = "nl.x-services.plugins.toast/Toast+UIView.m"; sourceTree = "<group>"; };
288765FC0DF74451002DB57D /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
2F66F04C3AA942779C1C4F95 /* UIApplication+APPLocalNotification.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "UIApplication+APPLocalNotification.m"; path = "de.appplant.cordova.plugin.local-notification/UIApplication+APPLocalNotification.m"; sourceTree = "<group>"; };
301BF52D109A57CC0062928A /* CordovaLib.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = CordovaLib.xcodeproj; path = CordovaLib/CordovaLib.xcodeproj; sourceTree = "<group>"; };
301BF56E109A69640062928A /* www */ = {isa = PBXFileReference; lastKnownFileType = folder; path = www; sourceTree = SOURCE_ROOT; };
302D95EE14D2391D003F00A1 /* MainViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MainViewController.h; sourceTree = "<group>"; };
......@@ -95,7 +98,14 @@
30C1856519D5FC0A00212699 /* icon-60@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-60@3x.png"; sourceTree = "<group>"; };
30FC414816E50CA1004E6F35 /* icon-72@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-72@2x.png"; sourceTree = "<group>"; };
32CA4F630368D1EE00C91783 /* NotificationExample-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NotificationExample-Prefix.pch"; sourceTree = "<group>"; };
358531870FE9418D801CA17D /* Toast.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Toast.m; path = "nl.x-services.plugins.toast/Toast.m"; sourceTree = "<group>"; };
3D318D53B4C1444BAAA6DAF1 /* APPLocalNotificationOptions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = APPLocalNotificationOptions.m; path = "de.appplant.cordova.plugin.local-notification/APPLocalNotificationOptions.m"; sourceTree = "<group>"; };
57141DABDB564FD5ADE82848 /* AppDelegate+APPRegisterUserNotificationSettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "AppDelegate+APPRegisterUserNotificationSettings.h"; path = "de.appplant.cordova.common.registerusernotificationsettings/AppDelegate+APPRegisterUserNotificationSettings.h"; sourceTree = "<group>"; };
5B1594DC16A7569C00FEF299 /* AssetsLibrary.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AssetsLibrary.framework; path = System/Library/Frameworks/AssetsLibrary.framework; sourceTree = SDKROOT; };
65E6CB261F3B4A1D990CDFD0 /* APPLocalNotificationOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = APPLocalNotificationOptions.h; path = "de.appplant.cordova.plugin.local-notification/APPLocalNotificationOptions.h"; sourceTree = "<group>"; };
751EA302B0C545C1ABD2CFB7 /* Toast+UIView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "Toast+UIView.h"; path = "nl.x-services.plugins.toast/Toast+UIView.h"; sourceTree = "<group>"; };
754762A7EDBD428EAA6B1370 /* APPLocalNotification.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = APPLocalNotification.m; path = "de.appplant.cordova.plugin.local-notification/APPLocalNotification.m"; sourceTree = "<group>"; };
78A8B88BC41248BBADACCABB /* UIApplication+APPLocalNotification.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UIApplication+APPLocalNotification.h"; path = "de.appplant.cordova.plugin.local-notification/UIApplication+APPLocalNotification.h"; sourceTree = "<group>"; };
7E7966D41810823500FA85AD /* icon-40.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-40.png"; sourceTree = "<group>"; };
7E7966D51810823500FA85AD /* icon-40@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-40@2x.png"; sourceTree = "<group>"; };
7E7966D61810823500FA85AD /* icon-50.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-50.png"; sourceTree = "<group>"; };
......@@ -107,26 +117,17 @@
7E7966DC1810823500FA85AD /* icon-small.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-small.png"; sourceTree = "<group>"; };
7E7966DD1810823500FA85AD /* icon-small@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-small@2x.png"; sourceTree = "<group>"; };
8D1107310486CEB800E47090 /* NotificationExample-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "NotificationExample-Info.plist"; path = "../NotificationExample-Info.plist"; plistStructureDefinitionIdentifier = "com.apple.xcode.plist.structure-definition.iphone.info-plist"; sourceTree = "<group>"; };
97129848CDCC42118CF1C40D /* QuartzCore.framework */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
9D377024246144729DE8F96F /* CDVDevice.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVDevice.m; path = "cordova-plugin-device/CDVDevice.m"; sourceTree = "<group>"; };
D4A0D8751607E02300AEF8BB /* Default-568h@2x~iphone.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x~iphone.png"; sourceTree = "<group>"; };
EB87FDF21871DA7A0020F90C /* merges */ = {isa = PBXFileReference; lastKnownFileType = folder; name = merges; path = ../../merges; sourceTree = "<group>"; };
D5869E30F00647C1A2399FAC /* AppDelegate+APPRegisterUserNotificationSettings.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "AppDelegate+APPRegisterUserNotificationSettings.m"; path = "de.appplant.cordova.common.registerusernotificationsettings/AppDelegate+APPRegisterUserNotificationSettings.m"; sourceTree = "<group>"; };
D702377109864DACBB7B7576 /* UILocalNotification+APPLocalNotification.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UILocalNotification+APPLocalNotification.h"; path = "de.appplant.cordova.plugin.local-notification/UILocalNotification+APPLocalNotification.h"; sourceTree = "<group>"; };
DA04C6D1451C4D9BA01968ED /* Toast.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Toast.h; path = "nl.x-services.plugins.toast/Toast.h"; sourceTree = "<group>"; };
EB87FDF31871DA8E0020F90C /* www */ = {isa = PBXFileReference; lastKnownFileType = folder; name = www; path = ../../www; sourceTree = "<group>"; };
EB87FDF41871DAF40020F90C /* config.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = config.xml; path = ../../config.xml; sourceTree = "<group>"; };
F840E1F0165FE0F500CFE078 /* config.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = config.xml; path = "NotificationExample/config.xml"; sourceTree = "<group>"; };
49A41E49185E401B9D6E65C6 /* Toast+UIView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = "Toast+UIView.m"; path = "nl.x-services.plugins.toast/Toast+UIView.m"; sourceTree = "<group>"; fileEncoding = 4; };
24E7095CA0544A92B37F596F /* Toast.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = "Toast.m"; path = "nl.x-services.plugins.toast/Toast.m"; sourceTree = "<group>"; fileEncoding = 4; };
FB4AA09C700F48A197160E9E /* Toast+UIView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "Toast+UIView.h"; path = "nl.x-services.plugins.toast/Toast+UIView.h"; sourceTree = "<group>"; fileEncoding = 4; };
AD82EA3E498F499983361E75 /* Toast.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "Toast.h"; path = "nl.x-services.plugins.toast/Toast.h"; sourceTree = "<group>"; fileEncoding = 4; };
5D3ECFAF1EDE404BA6652960 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = "QuartzCore.framework"; path = "System/Library/Frameworks/QuartzCore.framework"; sourceTree = SDKROOT; fileEncoding = 4; };
23D17A20B14445CB8E1A008A /* CDVDevice.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = "CDVDevice.m"; path = "org.apache.cordova.device/CDVDevice.m"; sourceTree = "<group>"; fileEncoding = 4; };
2A4D614CE3754A368505D090 /* CDVDevice.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "CDVDevice.h"; path = "org.apache.cordova.device/CDVDevice.h"; sourceTree = "<group>"; fileEncoding = 4; };
979507619BA5418E88EFC889 /* APPLocalNotification.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = "APPLocalNotification.m"; path = "de.appplant.cordova.plugin.local-notification/APPLocalNotification.m"; sourceTree = "<group>"; fileEncoding = 4; };
ADF52FF21A8D45B19B24BCDA /* APPLocalNotificationOptions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = "APPLocalNotificationOptions.m"; path = "de.appplant.cordova.plugin.local-notification/APPLocalNotificationOptions.m"; sourceTree = "<group>"; fileEncoding = 4; };
929D5875A2EE490BAFAC25C3 /* UIApplication+APPLocalNotification.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = "UIApplication+APPLocalNotification.m"; path = "de.appplant.cordova.plugin.local-notification/UIApplication+APPLocalNotification.m"; sourceTree = "<group>"; fileEncoding = 4; };
632B9B22D7494695ACFAA5AF /* UILocalNotification+APPLocalNotification.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = "UILocalNotification+APPLocalNotification.m"; path = "de.appplant.cordova.plugin.local-notification/UILocalNotification+APPLocalNotification.m"; sourceTree = "<group>"; fileEncoding = 4; };
747AE3623EC444D4946724DF /* APPLocalNotification.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "APPLocalNotification.h"; path = "de.appplant.cordova.plugin.local-notification/APPLocalNotification.h"; sourceTree = "<group>"; fileEncoding = 4; };
F69403A62FD04397991717E1 /* APPLocalNotificationOptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "APPLocalNotificationOptions.h"; path = "de.appplant.cordova.plugin.local-notification/APPLocalNotificationOptions.h"; sourceTree = "<group>"; fileEncoding = 4; };
4B7A82BEDCE84E8AA3F74D72 /* UIApplication+APPLocalNotification.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "UIApplication+APPLocalNotification.h"; path = "de.appplant.cordova.plugin.local-notification/UIApplication+APPLocalNotification.h"; sourceTree = "<group>"; fileEncoding = 4; };
04BD28959C1243839D6E7419 /* UILocalNotification+APPLocalNotification.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "UILocalNotification+APPLocalNotification.h"; path = "de.appplant.cordova.plugin.local-notification/UILocalNotification+APPLocalNotification.h"; sourceTree = "<group>"; fileEncoding = 4; };
F840E1F0165FE0F500CFE078 /* config.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = config.xml; path = NotificationExample/config.xml; sourceTree = "<group>"; };
F84A063F3D7643B199254183 /* CDVDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVDevice.h; path = "cordova-plugin-device/CDVDevice.h"; sourceTree = "<group>"; };
FA53F16C55784362BAB47C99 /* APPLocalNotification.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = APPLocalNotification.h; path = "de.appplant.cordova.plugin.local-notification/APPLocalNotification.h"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
......@@ -138,7 +139,7 @@
301BF552109A68D80062928A /* libCordova.a in Frameworks */,
288765FD0DF74451002DB57D /* CoreGraphics.framework in Frameworks */,
305D5FD1115AB8F900A74A75 /* MobileCoreServices.framework in Frameworks */,
35024486F61C43DEBCE510AD /* QuartzCore.framework in Frameworks */,
CC26E958D783460CB096D087 /* QuartzCore.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
......@@ -155,7 +156,7 @@
1D3623250D0F684500981E51 /* AppDelegate.m */,
);
name = Classes;
path = "NotificationExample/Classes";
path = NotificationExample/Classes;
sourceTree = SOURCE_ROOT;
};
19C28FACFE9D520D11CA2CBB /* Products */ = {
......@@ -171,7 +172,6 @@
children = (
EB87FDF41871DAF40020F90C /* config.xml */,
EB87FDF31871DA8E0020F90C /* www */,
EB87FDF21871DA7A0020F90C /* merges */,
EB87FDF11871DA420020F90C /* Staging */,
301BF52D109A57CC0062928A /* CordovaLib.xcodeproj */,
080E96DDFE201D6D7F000001 /* Classes */,
......@@ -191,7 +191,7 @@
29B97316FDCFA39411CA2CEA /* main.m */,
);
name = "Other Sources";
path = "NotificationExample";
path = NotificationExample;
sourceTree = "<group>";
};
29B97317FDCFA39411CA2CEA /* Resources */ = {
......@@ -202,7 +202,7 @@
8D1107310486CEB800E47090 /* NotificationExample-Info.plist */,
);
name = Resources;
path = "NotificationExample/Resources";
path = NotificationExample/Resources;
sourceTree = "<group>";
};
29B97323FDCFA39411CA2CEA /* Frameworks */ = {
......@@ -211,7 +211,7 @@
5B1594DC16A7569C00FEF299 /* AssetsLibrary.framework */,
288765FC0DF74451002DB57D /* CoreGraphics.framework */,
305D5FD0115AB8F900A74A75 /* MobileCoreServices.framework */,
5D3ECFAF1EDE404BA6652960 /* QuartzCore.framework */,
97129848CDCC42118CF1C40D /* QuartzCore.framework */,
);
name = Frameworks;
sourceTree = "<group>";
......@@ -227,23 +227,25 @@
307C750510C5A3420062BCA9 /* Plugins */ = {
isa = PBXGroup;
children = (
49A41E49185E401B9D6E65C6 /* Toast+UIView.m */,
24E7095CA0544A92B37F596F /* Toast.m */,
FB4AA09C700F48A197160E9E /* Toast+UIView.h */,
AD82EA3E498F499983361E75 /* Toast.h */,
23D17A20B14445CB8E1A008A /* CDVDevice.m */,
2A4D614CE3754A368505D090 /* CDVDevice.h */,
979507619BA5418E88EFC889 /* APPLocalNotification.m */,
ADF52FF21A8D45B19B24BCDA /* APPLocalNotificationOptions.m */,
929D5875A2EE490BAFAC25C3 /* UIApplication+APPLocalNotification.m */,
632B9B22D7494695ACFAA5AF /* UILocalNotification+APPLocalNotification.m */,
747AE3623EC444D4946724DF /* APPLocalNotification.h */,
F69403A62FD04397991717E1 /* APPLocalNotificationOptions.h */,
4B7A82BEDCE84E8AA3F74D72 /* UIApplication+APPLocalNotification.h */,
04BD28959C1243839D6E7419 /* UILocalNotification+APPLocalNotification.h */,
D5869E30F00647C1A2399FAC /* AppDelegate+APPRegisterUserNotificationSettings.m */,
57141DABDB564FD5ADE82848 /* AppDelegate+APPRegisterUserNotificationSettings.h */,
1DE50EBD09D2455DBC5D351E /* Toast+UIView.m */,
358531870FE9418D801CA17D /* Toast.m */,
751EA302B0C545C1ABD2CFB7 /* Toast+UIView.h */,
DA04C6D1451C4D9BA01968ED /* Toast.h */,
9D377024246144729DE8F96F /* CDVDevice.m */,
F84A063F3D7643B199254183 /* CDVDevice.h */,
754762A7EDBD428EAA6B1370 /* APPLocalNotification.m */,
3D318D53B4C1444BAAA6DAF1 /* APPLocalNotificationOptions.m */,
2F66F04C3AA942779C1C4F95 /* UIApplication+APPLocalNotification.m */,
0EABFA908C98474CA4F6C65A /* UILocalNotification+APPLocalNotification.m */,
FA53F16C55784362BAB47C99 /* APPLocalNotification.h */,
65E6CB261F3B4A1D990CDFD0 /* APPLocalNotificationOptions.h */,
78A8B88BC41248BBADACCABB /* UIApplication+APPLocalNotification.h */,
D702377109864DACBB7B7576 /* UILocalNotification+APPLocalNotification.h */,
);
name = Plugins;
path = "NotificationExample/Plugins";
path = NotificationExample/Plugins;
sourceTree = SOURCE_ROOT;
};
308D052D1370CCF300D202BF /* icons */ = {
......@@ -311,8 +313,8 @@
dependencies = (
301BF551109A68C00062928A /* PBXTargetDependency */,
);
name = "NotificationExample";
productName = "NotificationExample";
name = NotificationExample;
productName = NotificationExample;
productReference = 1D6058910D05DD3D006BFB54 /* NotificationExample.app */;
productType = "com.apple.product-type.application";
};
......@@ -324,7 +326,7 @@
attributes = {
LastUpgradeCheck = 510;
};
buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "__CLI__" */;
buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "NotificationExample" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 1;
......@@ -412,7 +414,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "cordova/lib/copy-www-build-step.sh";
shellScript = "NODEJS_PATH=/usr/local/bin; NVM_NODE_PATH=~/.nvm/versions/node/`nvm version 2>/dev/null`/bin; N_NODE_PATH=`find /usr/local/n/versions/node/* -maxdepth 0 -type d 2>/dev/null | tail -1`/bin; XCODE_NODE_PATH=`xcode-select --print-path`/usr/share/xcs/Node/bin; PATH=$NODEJS_PATH:$NVM_NODE_PATH:$N_NODE_PATH:$XCODE_NODE_PATH:$PATH && node cordova/lib/copy-www-build-step.js";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
......@@ -425,13 +427,14 @@
1D60589B0D05DD56006BFB54 /* main.m in Sources */,
1D3623260D0F684500981E51 /* AppDelegate.m in Sources */,
302D95F114D2391D003F00A1 /* MainViewController.m in Sources */,
6B489B4BC70B42A1A1ED596C /* Toast+UIView.m in Sources */,
380ACB2600604A63A2DB79FF /* Toast.m in Sources */,
87985801CA7141F2ABDFA26C /* CDVDevice.m in Sources */,
BCD48564514D4772B2A4B8A9 /* APPLocalNotification.m in Sources */,
1D15D09292314FE1B88509DA /* APPLocalNotificationOptions.m in Sources */,
8821D32BBC744C43AA03747E /* UIApplication+APPLocalNotification.m in Sources */,
69435A24D7CD463EBA565B60 /* UILocalNotification+APPLocalNotification.m in Sources */,
1C584EB51F3C426D8A25DAAF /* AppDelegate+APPRegisterUserNotificationSettings.m in Sources */,
0ECEF97594F04776B7BE0C66 /* Toast+UIView.m in Sources */,
9149ECD9BBCA4D8E9134ABC1 /* Toast.m in Sources */,
E2C8C56228EF4650921A8C13 /* CDVDevice.m in Sources */,
AD36A476BF534005AC4468ED /* APPLocalNotification.m in Sources */,
EFFF31CCFEC944568CED9AF2 /* APPLocalNotificationOptions.m in Sources */,
AF44493D8C1E426D98DF16EF /* UIApplication+APPLocalNotification.m in Sources */,
297157BA33654D9294C2E907 /* UILocalNotification+APPLocalNotification.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
......@@ -472,7 +475,7 @@
"-weak-lSystem",
"-ObjC",
);
PRODUCT_NAME = "NotificationExample";
PRODUCT_NAME = NotificationExample;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
......@@ -501,7 +504,7 @@
"-weak-lSystem",
"-ObjC",
);
PRODUCT_NAME = "NotificationExample";
PRODUCT_NAME = NotificationExample;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
......@@ -605,7 +608,7 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
C01FCF4E08A954540054247B /* Build configuration list for PBXProject "__CLI__" */ = {
C01FCF4E08A954540054247B /* Build configuration list for PBXProject "NotificationExample" */ = {
isa = XCConfigurationList;
buildConfigurations = (
C01FCF4F08A954540054247B /* Debug */,
......
......@@ -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.
[![Build Status](https://travis-ci.org/isaacs/node-glob.svg?branch=master)](https://travis-ci.org/isaacs/node-glob/) [![Dependency Status](https://david-dm.org/isaacs/node-glob.svg)](https://david-dm.org/isaacs/node-glob) [![devDependency Status](https://david-dm.org/isaacs/node-glob/dev-status.svg)](https://david-dm.org/isaacs/node-glob#info=devDependencies) [![optionalDependency Status](https://david-dm.org/isaacs/node-glob/optional-status.svg)](https://david-dm.org/isaacs/node-glob#info=optionalDependencies)
# Glob
Match files using the patterns the shell uses, like stars and stuff.
This is a glob implementation in JavaScript. It uses the `minimatch`
library to do its matching.
![](oh-my-glob.gif)
## Usage
```javascript
var glob = require("glob")
// options is optional
glob("**/*.js", options, function (er, files) {
// files is an array of filenames.
// If the `nonull` option is set, and nothing
// was found, then files is ["**/*.js"]
// er is an error object or null.
})
```
## Glob Primer
"Globs" are the patterns you type when you do stuff like `ls *.js` on
the command line, or put `build/*` in a `.gitignore` file.
Before parsing the path part patterns, braced sections are expanded
into a set. Braced sections start with `{` and end with `}`, with any
number of comma-delimited sections within. Braced sections may contain
slash characters, so `a{/b/c,bcd}` would expand into `a/b/c` and `abcd`.
The following characters have special magic meaning when used in a
path portion:
* `*` Matches 0 or more characters in a single path portion
* `?` Matches 1 character
* `[...]` Matches a range of characters, similar to a RegExp range.
If the first character of the range is `!` or `^` then it matches
any character not in the range.
* `!(pattern|pattern|pattern)` Matches anything that does not match
any of the patterns provided.
* `?(pattern|pattern|pattern)` Matches zero or one occurrence of the
patterns provided.
* `+(pattern|pattern|pattern)` Matches one or more occurrences of the
patterns provided.
* `*(a|b|c)` Matches zero or more occurrences of the patterns provided
* `@(pattern|pat*|pat?erN)` Matches exactly one of the patterns
provided
* `**` If a "globstar" is alone in a path portion, then it matches
zero or more directories and subdirectories searching for matches.
It does not crawl symlinked directories.
### Dots
If a file or directory path portion has a `.` as the first character,
then it will not match any glob pattern unless that pattern's
corresponding path part also has a `.` as its first character.
For example, the pattern `a/.*/c` would match the file at `a/.b/c`.
However the pattern `a/*/c` would not, because `*` does not start with
a dot character.
You can make glob treat dots as normal characters by setting
`dot:true` in the options.
### Basename Matching
If you set `matchBase:true` in the options, and the pattern has no
slashes in it, then it will seek for any file anywhere in the tree
with a matching basename. For example, `*.js` would match
`test/simple/basic.js`.
### Negation
The intent for negation would be for a pattern starting with `!` to
match everything that *doesn't* match the supplied pattern. However,
the implementation is weird, and for the time being, this should be
avoided. The behavior is deprecated in version 5, and will be removed
entirely in version 6.
### Empty Sets
If no matching files are found, then an empty array is returned. This
differs from the shell, where the pattern itself is returned. For
example:
$ echo a*s*d*f
a*s*d*f
To get the bash-style behavior, set the `nonull:true` in the options.
### See Also:
* `man sh`
* `man bash` (Search for "Pattern Matching")
* `man 3 fnmatch`
* `man 5 gitignore`
* [minimatch documentation](https://github.com/isaacs/minimatch)
## glob.hasMagic(pattern, [options])
Returns `true` if there are any special characters in the pattern, and
`false` otherwise.
Note that the options affect the results. If `noext:true` is set in
the options object, then `+(a|b)` will not be considered a magic
pattern. If the pattern has a brace expansion, like `a/{b/c,x/y}`
then that is considered magical, unless `nobrace:true` is set in the
options.
## glob(pattern, [options], cb)
* `pattern` {String} Pattern to be matched
* `options` {Object}
* `cb` {Function}
* `err` {Error | null}
* `matches` {Array<String>} filenames found matching the pattern
Perform an asynchronous glob search.
## glob.sync(pattern, [options])
* `pattern` {String} Pattern to be matched
* `options` {Object}
* return: {Array<String>} filenames found matching the pattern
Perform a synchronous glob search.
## Class: glob.Glob
Create a Glob object by instantiating the `glob.Glob` class.
```javascript
var Glob = require("glob").Glob
var mg = new Glob(pattern, options, cb)
```
It's an EventEmitter, and starts walking the filesystem to find matches
immediately.
### new glob.Glob(pattern, [options], [cb])
* `pattern` {String} pattern to search for
* `options` {Object}
* `cb` {Function} Called when an error occurs, or matches are found
* `err` {Error | null}
* `matches` {Array<String>} filenames found matching the pattern
Note that if the `sync` flag is set in the options, then matches will
be immediately available on the `g.found` member.
### Properties
* `minimatch` The minimatch object that the glob uses.
* `options` The options object passed in.
* `aborted` Boolean which is set to true when calling `abort()`. There
is no way at this time to continue a glob search after aborting, but
you can re-use the statCache to avoid having to duplicate syscalls.
* `cache` Convenience object. Each field has the following possible
values:
* `false` - Path does not exist
* `true` - Path exists
* `'DIR'` - Path exists, and is not a directory
* `'FILE'` - Path exists, and is a directory
* `[file, entries, ...]` - Path exists, is a directory, and the
array value is the results of `fs.readdir`
* `statCache` Cache of `fs.stat` results, to prevent statting the same
path multiple times.
* `symlinks` A record of which paths are symbolic links, which is
relevant in resolving `**` patterns.
* `realpathCache` An optional object which is passed to `fs.realpath`
to minimize unnecessary syscalls. It is stored on the instantiated
Glob object, and may be re-used.
### Events
* `end` When the matching is finished, this is emitted with all the
matches found. If the `nonull` option is set, and no match was found,
then the `matches` list contains the original pattern. The matches
are sorted, unless the `nosort` flag is set.
* `match` Every time a match is found, this is emitted with the matched.
* `error` Emitted when an unexpected error is encountered, or whenever
any fs error occurs if `options.strict` is set.
* `abort` When `abort()` is called, this event is raised.
### Methods
* `pause` Temporarily stop the search
* `resume` Resume the search
* `abort` Stop the search forever
### Options
All the options that can be passed to Minimatch can also be passed to
Glob to change pattern matching behavior. Also, some have been added,
or have glob-specific ramifications.
All options are false by default, unless otherwise noted.
All options are added to the Glob object, as well.
If you are running many `glob` operations, you can pass a Glob object
as the `options` argument to a subsequent operation to shortcut some
`stat` and `readdir` calls. At the very least, you may pass in shared
`symlinks`, `statCache`, `realpathCache`, and `cache` options, so that
parallel glob operations will be sped up by sharing information about
the filesystem.
* `cwd` The current working directory in which to search. Defaults
to `process.cwd()`.
* `root` The place where patterns starting with `/` will be mounted
onto. Defaults to `path.resolve(options.cwd, "/")` (`/` on Unix
systems, and `C:\` or some such on Windows.)
* `dot` Include `.dot` files in normal matches and `globstar` matches.
Note that an explicit dot in a portion of the pattern will always
match dot files.
* `nomount` By default, a pattern starting with a forward-slash will be
"mounted" onto the root setting, so that a valid filesystem path is
returned. Set this flag to disable that behavior.
* `mark` Add a `/` character to directory matches. Note that this
requires additional stat calls.
* `nosort` Don't sort the results.
* `stat` Set to true to stat *all* results. This reduces performance
somewhat, and is completely unnecessary, unless `readdir` is presumed
to be an untrustworthy indicator of file existence.
* `silent` When an unusual error is encountered when attempting to
read a directory, a warning will be printed to stderr. Set the
`silent` option to true to suppress these warnings.
* `strict` When an unusual error is encountered when attempting to
read a directory, the process will just continue on in search of
other matches. Set the `strict` option to raise an error in these
cases.
* `cache` See `cache` property above. Pass in a previously generated
cache object to save some fs calls.
* `statCache` A cache of results of filesystem information, to prevent
unnecessary stat calls. While it should not normally be necessary
to set this, you may pass the statCache from one glob() call to the
options object of another, if you know that the filesystem will not
change between calls. (See "Race Conditions" below.)
* `symlinks` A cache of known symbolic links. You may pass in a
previously generated `symlinks` object to save `lstat` calls when
resolving `**` matches.
* `sync` DEPRECATED: use `glob.sync(pattern, opts)` instead.
* `nounique` In some cases, brace-expanded patterns can result in the
same file showing up multiple times in the result set. By default,
this implementation prevents duplicates in the result set. Set this
flag to disable that behavior.
* `nonull` Set to never return an empty set, instead returning a set
containing the pattern itself. This is the default in glob(3).
* `debug` Set to enable debug logging in minimatch and glob.
* `nobrace` Do not expand `{a,b}` and `{1..3}` brace sets.
* `noglobstar` Do not match `**` against multiple filenames. (Ie,
treat it as a normal `*` instead.)
* `noext` Do not match `+(a|b)` "extglob" patterns.
* `nocase` Perform a case-insensitive match. Note: on
case-insensitive filesystems, non-magic patterns will match by
default, since `stat` and `readdir` will not raise errors.
* `matchBase` Perform a basename-only match if the pattern does not
contain any slash characters. That is, `*.js` would be treated as
equivalent to `**/*.js`, matching all js files in all directories.
* `nonull` Return the pattern when no matches are found.
* `nodir` Do not match directories, only files. (Note: to match
*only* directories, simply put a `/` at the end of the pattern.)
* `ignore` Add a pattern or an array of patterns to exclude matches.
* `follow` Follow symlinked directories when expanding `**` patterns.
Note that this can result in a lot of duplicate references in the
presence of cyclic links.
* `realpath` Set to true to call `fs.realpath` on all of the results.
In the case of a symlink that cannot be resolved, the full absolute
path to the matched entry is returned (though it will usually be a
broken symlink)
* `nonegate` Suppress deprecated `negate` behavior. (See below.)
Default=true
* `nocomment` Suppress deprecated `comment` behavior. (See below.)
Default=true
## Comparisons to other fnmatch/glob implementations
While strict compliance with the existing standards is a worthwhile
goal, some discrepancies exist between node-glob and other
implementations, and are intentional.
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.3, 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.
Note that symlinked directories are not crawled as part of a `**`,
though their contents may match against subsequent portions of the
pattern. This prevents infinite loops and duplicates and the like.
If an escaped pattern has no matches, and the `nonull` flag is set,
then glob returns the pattern as-provided, rather than
interpreting the character escapes. For example,
`glob.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.
### Comments and Negation
**Note**: In version 5 of this module, negation and comments are
**disabled** by default. You can explicitly set `nonegate:false` or
`nocomment:false` to re-enable them. They are going away entirely in
version 6.
The intent for negation would be for a pattern starting with `!` to
match everything that *doesn't* match the supplied pattern. However,
the implementation is weird. It is better to use the `ignore` option
to set a pattern or set of patterns to exclude from matches. If you
want the "everything except *x*" type of behavior, you can use `**` as
the main pattern, and set an `ignore` for the things to exclude.
The comments feature is added in minimatch, primarily to more easily
support use cases like ignore files, where a `#` at the start of a
line makes the pattern "empty". However, in the context of a
straightforward filesystem globber, "comments" don't make much sense.
## Windows
**Please only use forward-slashes in glob expressions.**
Though windows uses either `/` or `\` as its path separator, only `/`
characters are used by this glob implementation. You must use
forward-slashes **only** in glob expressions. Back-slashes will always
be interpreted as escape characters, not path separators.
Results from absolute patterns such as `/foo/*` are mounted onto the
root setting using `path.join`. On windows, this will by default result
in `/foo/*` matching `C:\foo\bar.txt`.
## Race Conditions
Glob searching, by its very nature, is susceptible to race conditions,
since it relies on directory walking and such.
As a result, it is possible that a file that exists when glob looks for
it may have been deleted or modified by the time it returns the result.
As part of its internal implementation, this program caches all stat
and readdir calls that it makes, in order to cut down on system
overhead. However, this also makes it even more susceptible to races,
especially if the cache or statCache objects are reused between glob
calls.
Users are thus advised not to use a glob result as a guarantee of
filesystem state in the face of rapid changes. For the vast majority
of operations, this is never a problem.
## Contributing
Any change to behavior (including bugfixes) must come with a test.
Patches that fail tests or reduce performance will be rejected.
```
# to run tests
npm test
# to re-generate test fixtures
npm run test-regen
# to benchmark against bash/zsh
npm run bench
# to profile javascript
npm run prof
```
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))
})
}
// Approach:
//
// 1. Get the minimatch set
// 2. For each pattern in the set, PROCESS(pattern, false)
// 3. Store matches per-set, then uniq them
//
// PROCESS(pattern, inGlobStar)
// Get the first [n] items from pattern that are all strings
// Join these together. This is PREFIX.
// If there is no more remaining, then stat(PREFIX) and
// add to matches if it succeeds. END.
//
// If inGlobStar and PREFIX is symlink and points to dir
// set ENTRIES = []
// else readdir(PREFIX) as ENTRIES
// If fail, END
//
// with ENTRIES
// If pattern[n] is GLOBSTAR
// // handle the case where the globstar match is empty
// // by pruning it out, and testing the resulting pattern
// PROCESS(pattern[0..n] + pattern[n+1 .. $], false)
// // handle other cases.
// for ENTRY in ENTRIES (not dotfiles)
// // attach globstar + tail onto the entry
// // Mark that this entry is a globstar match
// PROCESS(pattern[0..n] + ENTRY + pattern[n .. $], true)
//
// else // not globstar
// for ENTRY in ENTRIES (not dotfiles, unless pattern[n] is dot)
// Test ENTRY against pattern[n]
// If fails, continue
// If passes, PROCESS(pattern[0..n] + item + pattern[n+1 .. $])
//
// Caveat:
// Cache all stats and readdirs results to minimize syscall. Since all
// we ever care about is existence and directory-ness, we can just keep
// `true` for files, and [children,...] for directories, or `false` for
// things that don't exist.
module.exports = glob
var fs = require('fs')
var minimatch = require('minimatch')
var Minimatch = minimatch.Minimatch
var inherits = require('inherits')
var EE = require('events').EventEmitter
var path = require('path')
var assert = require('assert')
var isAbsolute = require('path-is-absolute')
var globSync = require('./sync.js')
var common = require('./common.js')
var alphasort = common.alphasort
var alphasorti = common.alphasorti
var setopts = common.setopts
var ownProp = common.ownProp
var inflight = require('inflight')
var util = require('util')
var childrenIgnored = common.childrenIgnored
var once = require('once')
function glob (pattern, options, cb) {
if (typeof options === 'function') cb = options, options = {}
if (!options) options = {}
if (options.sync) {
if (cb)
throw new TypeError('callback provided to sync glob')
return globSync(pattern, options)
}
return new Glob(pattern, options, cb)
}
glob.sync = globSync
var GlobSync = glob.GlobSync = globSync.GlobSync
// old api surface
glob.glob = glob
glob.hasMagic = function (pattern, options_) {
var options = util._extend({}, options_)
options.noprocess = true
var g = new Glob(pattern, options)
var set = g.minimatch.set
if (set.length > 1)
return true
for (var j = 0; j < set[0].length; j++) {
if (typeof set[0][j] !== 'string')
return true
}
return false
}
glob.Glob = Glob
inherits(Glob, EE)
function Glob (pattern, options, cb) {
if (typeof options === 'function') {
cb = options
options = null
}
if (options && options.sync) {
if (cb)
throw new TypeError('callback provided to sync glob')
return new GlobSync(pattern, options)
}
if (!(this instanceof Glob))
return new Glob(pattern, options, cb)
setopts(this, pattern, options)
this._didRealPath = false
// process each pattern in the minimatch set
var n = this.minimatch.set.length
// The matches are stored as {<filename>: true,...} so that
// duplicates are automagically pruned.
// Later, we do an Object.keys() on these.
// Keep them as a list so we can fill in when nonull is set.
this.matches = new Array(n)
if (typeof cb === 'function') {
cb = once(cb)
this.on('error', cb)
this.on('end', function (matches) {
cb(null, matches)
})
}
var self = this
var n = this.minimatch.set.length
this._processing = 0
this.matches = new Array(n)
this._emitQueue = []
this._processQueue = []
this.paused = false
if (this.noprocess)
return this
if (n === 0)
return done()
for (var i = 0; i < n; i ++) {
this._process(this.minimatch.set[i], i, false, done)
}
function done () {
--self._processing
if (self._processing <= 0)
self._finish()
}
}
Glob.prototype._finish = function () {
assert(this instanceof Glob)
if (this.aborted)
return
if (this.realpath && !this._didRealpath)
return this._realpath()
common.finish(this)
this.emit('end', this.found)
}
Glob.prototype._realpath = function () {
if (this._didRealpath)
return
this._didRealpath = true
var n = this.matches.length
if (n === 0)
return this._finish()
var self = this
for (var i = 0; i < this.matches.length; i++)
this._realpathSet(i, next)
function next () {
if (--n === 0)
self._finish()
}
}
Glob.prototype._realpathSet = function (index, cb) {
var matchset = this.matches[index]
if (!matchset)
return cb()
var found = Object.keys(matchset)
var self = this
var n = found.length
if (n === 0)
return cb()
var set = this.matches[index] = Object.create(null)
found.forEach(function (p, i) {
// If there's a problem with the stat, then it means that
// one or more of the links in the realpath couldn't be
// resolved. just return the abs value in that case.
p = self._makeAbs(p)
fs.realpath(p, self.realpathCache, function (er, real) {
if (!er)
set[real] = true
else if (er.syscall === 'stat')
set[p] = true
else
self.emit('error', er) // srsly wtf right here
if (--n === 0) {
self.matches[index] = set
cb()
}
})
})
}
Glob.prototype._mark = function (p) {
return common.mark(this, p)
}
Glob.prototype._makeAbs = function (f) {
return common.makeAbs(this, f)
}
Glob.prototype.abort = function () {
this.aborted = true
this.emit('abort')
}
Glob.prototype.pause = function () {
if (!this.paused) {
this.paused = true
this.emit('pause')
}
}
Glob.prototype.resume = function () {
if (this.paused) {
this.emit('resume')
this.paused = false
if (this._emitQueue.length) {
var eq = this._emitQueue.slice(0)
this._emitQueue.length = 0
for (var i = 0; i < eq.length; i ++) {
var e = eq[i]
this._emitMatch(e[0], e[1])
}
}
if (this._processQueue.length) {
var pq = this._processQueue.slice(0)
this._processQueue.length = 0
for (var i = 0; i < pq.length; i ++) {
var p = pq[i]
this._processing--
this._process(p[0], p[1], p[2], p[3])
}
}
}
}
Glob.prototype._process = function (pattern, index, inGlobStar, cb) {
assert(this instanceof Glob)
assert(typeof cb === 'function')
if (this.aborted)
return
this._processing++
if (this.paused) {
this._processQueue.push([pattern, index, inGlobStar, cb])
return
}
//console.error('PROCESS %d', this._processing, pattern)
// Get the first [n] parts of pattern that are all strings.
var n = 0
while (typeof pattern[n] === 'string') {
n ++
}
// now n is the index of the first one that is *not* a string.
// see if there's anything else
var prefix
switch (n) {
// if not, then this is rather simple
case pattern.length:
this._processSimple(pattern.join('/'), index, cb)
return
case 0:
// pattern *starts* with some non-trivial item.
// going to readdir(cwd), but not include the prefix in matches.
prefix = null
break
default:
// pattern has some string bits in the front.
// whatever it starts with, whether that's 'absolute' like /foo/bar,
// or 'relative' like '../baz'
prefix = pattern.slice(0, n).join('/')
break
}
var remain = pattern.slice(n)
// get the list of entries.
var read
if (prefix === null)
read = '.'
else if (isAbsolute(prefix) || isAbsolute(pattern.join('/'))) {
if (!prefix || !isAbsolute(prefix))
prefix = '/' + prefix
read = prefix
} else
read = prefix
var abs = this._makeAbs(read)
//if ignored, skip _processing
if (childrenIgnored(this, read))
return cb()
var isGlobStar = remain[0] === minimatch.GLOBSTAR
if (isGlobStar)
this._processGlobStar(prefix, read, abs, remain, index, inGlobStar, cb)
else
this._processReaddir(prefix, read, abs, remain, index, inGlobStar, cb)
}
Glob.prototype._processReaddir = function (prefix, read, abs, remain, index, inGlobStar, cb) {
var self = this
this._readdir(abs, inGlobStar, function (er, entries) {
return self._processReaddir2(prefix, read, abs, remain, index, inGlobStar, entries, cb)
})
}
Glob.prototype._processReaddir2 = function (prefix, read, abs, remain, index, inGlobStar, entries, cb) {
// if the abs isn't a dir, then nothing can match!
if (!entries)
return cb()
// It will only match dot entries if it starts with a dot, or if
// dot is set. Stuff like @(.foo|.bar) isn't allowed.
var pn = remain[0]
var negate = !!this.minimatch.negate
var rawGlob = pn._glob
var dotOk = this.dot || rawGlob.charAt(0) === '.'
var matchedEntries = []
for (var i = 0; i < entries.length; i++) {
var e = entries[i]
if (e.charAt(0) !== '.' || dotOk) {
var m
if (negate && !prefix) {
m = !e.match(pn)
} else {
m = e.match(pn)
}
if (m)
matchedEntries.push(e)
}
}
//console.error('prd2', prefix, entries, remain[0]._glob, matchedEntries)
var len = matchedEntries.length
// If there are no matched entries, then nothing matches.
if (len === 0)
return cb()
// if this is the last remaining pattern bit, then no need for
// an additional stat *unless* the user has specified mark or
// stat explicitly. We know they exist, since readdir returned
// them.
if (remain.length === 1 && !this.mark && !this.stat) {
if (!this.matches[index])
this.matches[index] = Object.create(null)
for (var i = 0; i < len; i ++) {
var e = matchedEntries[i]
if (prefix) {
if (prefix !== '/')
e = prefix + '/' + e
else
e = prefix + e
}
if (e.charAt(0) === '/' && !this.nomount) {
e = path.join(this.root, e)
}
this._emitMatch(index, e)
}
// This was the last one, and no stats were needed
return cb()
}
// now test all matched entries as stand-ins for that part
// of the pattern.
remain.shift()
for (var i = 0; i < len; i ++) {
var e = matchedEntries[i]
var newPattern
if (prefix) {
if (prefix !== '/')
e = prefix + '/' + e
else
e = prefix + e
}
this._process([e].concat(remain), index, inGlobStar, cb)
}
cb()
}
Glob.prototype._emitMatch = function (index, e) {
if (this.aborted)
return
if (this.matches[index][e])
return
if (this.paused) {
this._emitQueue.push([index, e])
return
}
var abs = this._makeAbs(e)
if (this.nodir) {
var c = this.cache[abs]
if (c === 'DIR' || Array.isArray(c))
return
}
if (this.mark)
e = this._mark(e)
this.matches[index][e] = true
var st = this.statCache[abs]
if (st)
this.emit('stat', e, st)
this.emit('match', e)
}
Glob.prototype._readdirInGlobStar = function (abs, cb) {
if (this.aborted)
return
// follow all symlinked directories forever
// just proceed as if this is a non-globstar situation
if (this.follow)
return this._readdir(abs, false, cb)
var lstatkey = 'lstat\0' + abs
var self = this
var lstatcb = inflight(lstatkey, lstatcb_)
if (lstatcb)
fs.lstat(abs, lstatcb)
function lstatcb_ (er, lstat) {
if (er)
return cb()
var isSym = lstat.isSymbolicLink()
self.symlinks[abs] = isSym
// If it's not a symlink or a dir, then it's definitely a regular file.
// don't bother doing a readdir in that case.
if (!isSym && !lstat.isDirectory()) {
self.cache[abs] = 'FILE'
cb()
} else
self._readdir(abs, false, cb)
}
}
Glob.prototype._readdir = function (abs, inGlobStar, cb) {
if (this.aborted)
return
cb = inflight('readdir\0'+abs+'\0'+inGlobStar, cb)
if (!cb)
return
//console.error('RD %j %j', +inGlobStar, abs)
if (inGlobStar && !ownProp(this.symlinks, abs))
return this._readdirInGlobStar(abs, cb)
if (ownProp(this.cache, abs)) {
var c = this.cache[abs]
if (!c || c === 'FILE')
return cb()
if (Array.isArray(c))
return cb(null, c)
}
var self = this
fs.readdir(abs, readdirCb(this, abs, cb))
}
function readdirCb (self, abs, cb) {
return function (er, entries) {
if (er)
self._readdirError(abs, er, cb)
else
self._readdirEntries(abs, entries, cb)
}
}
Glob.prototype._readdirEntries = function (abs, entries, cb) {
if (this.aborted)
return
// if we haven't asked to stat everything, then just
// assume that everything in there exists, so we can avoid
// having to stat it a second time.
if (!this.mark && !this.stat) {
for (var i = 0; i < entries.length; i ++) {
var e = entries[i]
if (abs === '/')
e = abs + e
else
e = abs + '/' + e
this.cache[e] = true
}
}
this.cache[abs] = entries
return cb(null, entries)
}
Glob.prototype._readdirError = function (f, er, cb) {
if (this.aborted)
return
// handle errors, and cache the information
switch (er.code) {
case 'ENOTDIR': // totally normal. means it *does* exist.
this.cache[this._makeAbs(f)] = 'FILE'
break
case 'ENOENT': // not terribly unusual
case 'ELOOP':
case 'ENAMETOOLONG':
case 'UNKNOWN':
this.cache[this._makeAbs(f)] = false
break
default: // some unusual error. Treat as failure.
this.cache[this._makeAbs(f)] = false
if (this.strict) {
this.emit('error', er)
// If the error is handled, then we abort
// if not, we threw out of here
this.abort()
}
if (!this.silent)
console.error('glob error', er)
break
}
return cb()
}
Glob.prototype._processGlobStar = function (prefix, read, abs, remain, index, inGlobStar, cb) {
var self = this
this._readdir(abs, inGlobStar, function (er, entries) {
self._processGlobStar2(prefix, read, abs, remain, index, inGlobStar, entries, cb)
})
}
Glob.prototype._processGlobStar2 = function (prefix, read, abs, remain, index, inGlobStar, entries, cb) {
//console.error('pgs2', prefix, remain[0], entries)
// no entries means not a dir, so it can never have matches
// foo.txt/** doesn't match foo.txt
if (!entries)
return cb()
// test without the globstar, and with every child both below
// and replacing the globstar.
var remainWithoutGlobStar = remain.slice(1)
var gspref = prefix ? [ prefix ] : []
var noGlobStar = gspref.concat(remainWithoutGlobStar)
// the noGlobStar pattern exits the inGlobStar state
this._process(noGlobStar, index, false, cb)
var isSym = this.symlinks[abs]
var len = entries.length
// If it's a symlink, and we're in a globstar, then stop
if (isSym && inGlobStar)
return cb()
for (var i = 0; i < len; i++) {
var e = entries[i]
if (e.charAt(0) === '.' && !this.dot)
continue
// these two cases enter the inGlobStar state
var instead = gspref.concat(entries[i], remainWithoutGlobStar)
this._process(instead, index, true, cb)
var below = gspref.concat(entries[i], remain)
this._process(below, index, true, cb)
}
cb()
}
Glob.prototype._processSimple = function (prefix, index, cb) {
// XXX review this. Shouldn't it be doing the mounting etc
// before doing stat? kinda weird?
var self = this
this._stat(prefix, function (er, exists) {
self._processSimple2(prefix, index, er, exists, cb)
})
}
Glob.prototype._processSimple2 = function (prefix, index, er, exists, cb) {
//console.error('ps2', prefix, exists)
if (!this.matches[index])
this.matches[index] = Object.create(null)
// If it doesn't exist, then just mark the lack of results
if (!exists)
return cb()
if (prefix && isAbsolute(prefix) && !this.nomount) {
var trail = /[\/\\]$/.test(prefix)
if (prefix.charAt(0) === '/') {
prefix = path.join(this.root, prefix)
} else {
prefix = path.resolve(this.root, prefix)
if (trail)
prefix += '/'
}
}
if (process.platform === 'win32')
prefix = prefix.replace(/\\/g, '/')
// Mark this as a match
this._emitMatch(index, prefix)
cb()
}
// Returns either 'DIR', 'FILE', or false
Glob.prototype._stat = function (f, cb) {
var abs = this._makeAbs(f)
var needDir = f.slice(-1) === '/'
if (f.length > this.maxLength)
return cb()
if (!this.stat && ownProp(this.cache, abs)) {
var c = this.cache[abs]
if (Array.isArray(c))
c = 'DIR'
// It exists, but maybe not how we need it
if (!needDir || c === 'DIR')
return cb(null, c)
if (needDir && c === 'FILE')
return cb()
// otherwise we have to stat, because maybe c=true
// if we know it exists, but not what it is.
}
var exists
var stat = this.statCache[abs]
if (stat !== undefined) {
if (stat === false)
return cb(null, stat)
else {
var type = stat.isDirectory() ? 'DIR' : 'FILE'
if (needDir && type === 'FILE')
return cb()
else
return cb(null, type, stat)
}
}
var self = this
var statcb = inflight('stat\0' + abs, lstatcb_)
if (statcb)
fs.lstat(abs, statcb)
function lstatcb_ (er, lstat) {
if (lstat && lstat.isSymbolicLink()) {
// If it's a symlink, then treat it as the target, unless
// the target does not exist, then treat it as a file.
return fs.stat(abs, function (er, stat) {
if (er)
self._stat2(f, abs, null, lstat, cb)
else
self._stat2(f, abs, er, stat, cb)
})
} else {
self._stat2(f, abs, er, lstat, cb)
}
}
}
Glob.prototype._stat2 = function (f, abs, er, stat, cb) {
if (er) {
this.statCache[abs] = false
return cb()
}
var needDir = f.slice(-1) === '/'
this.statCache[abs] = stat
if (abs.slice(-1) === '/' && !stat.isDirectory())
return cb(null, false, stat)
var c = stat.isDirectory() ? 'DIR' : 'FILE'
this.cache[abs] = this.cache[abs] || c
if (needDir && c !== 'DIR')
return cb()
return cb(null, c, stat)
}
{
"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.
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
module.exports = minimatch
minimatch.Minimatch = Minimatch
var path = { sep: '/' }
try {
path = require('path')
} catch (er) {}
var GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {}
var expand = require('brace-expansion')
// any single thing other than /
// don't need to escape / when using new RegExp()
var qmark = '[^/]'
// * => any number of characters
var star = qmark + '*?'
// ** when dots are allowed. Anything goes, except .. and .
// not (^ or / followed by one or two dots followed by $ or /),
// followed by anything, any number of times.
var twoStarDot = '(?:(?!(?:\\\/|^)(?:\\.{1,2})($|\\\/)).)*?'
// not a ^ or / followed by a dot,
// followed by anything, any number of times.
var twoStarNoDot = '(?:(?!(?:\\\/|^)\\.).)*?'
// characters that need to be escaped in RegExp.
var reSpecials = charSet('().*{}+?[]^$\\!')
// "abc" -> { a:true, b:true, c:true }
function charSet (s) {
return s.split('').reduce(function (set, c) {
set[c] = true
return set
}, {})
}
// normalizes slashes.
var slashSplit = /\/+/
minimatch.filter = filter
function filter (pattern, options) {
options = options || {}
return function (p, i, list) {
return minimatch(p, pattern, options)
}
}
function ext (a, b) {
a = a || {}
b = b || {}
var t = {}
Object.keys(b).forEach(function (k) {
t[k] = b[k]
})
Object.keys(a).forEach(function (k) {
t[k] = a[k]
})
return t
}
minimatch.defaults = function (def) {
if (!def || !Object.keys(def).length) return minimatch
var orig = minimatch
var m = function minimatch (p, pattern, options) {
return orig.minimatch(p, pattern, ext(def, options))
}
m.Minimatch = function Minimatch (pattern, options) {
return new orig.Minimatch(pattern, ext(def, options))
}
return m
}
Minimatch.defaults = function (def) {
if (!def || !Object.keys(def).length) return Minimatch
return minimatch.defaults(def).Minimatch
}
function minimatch (p, pattern, options) {
if (typeof pattern !== 'string') {
throw new TypeError('glob pattern string required')
}
if (!options) options = {}
// shortcut: comments match nothing.
if (!options.nocomment && pattern.charAt(0) === '#') {
return false
}
// "" only matches ""
if (pattern.trim() === '') return p === ''
return new Minimatch(pattern, options).match(p)
}
function Minimatch (pattern, options) {
if (!(this instanceof Minimatch)) {
return new Minimatch(pattern, options)
}
if (typeof pattern !== 'string') {
throw new TypeError('glob pattern string required')
}
if (!options) options = {}
pattern = pattern.trim()
// windows support: need to use /, not \
if (path.sep !== '/') {
pattern = pattern.split(path.sep).join('/')
}
this.options = options
this.set = []
this.pattern = pattern
this.regexp = null
this.negate = false
this.comment = false
this.empty = false
// make the set of regexps etc.
this.make()
}
Minimatch.prototype.debug = function () {}
Minimatch.prototype.make = make
function make () {
// don't do it more than once.
if (this._made) return
var pattern = this.pattern
var options = this.options
// empty patterns and comments match nothing.
if (!options.nocomment && pattern.charAt(0) === '#') {
this.comment = true
return
}
if (!pattern) {
this.empty = true
return
}
// step 1: figure out negation, etc.
this.parseNegate()
// step 2: expand braces
var set = this.globSet = this.braceExpand()
if (options.debug) this.debug = console.error
this.debug(this.pattern, set)
// step 3: now we have a set, so turn each one into a series of path-portion
// matching patterns.
// These will be regexps, except in the case of "**", which is
// set to the GLOBSTAR object for globstar behavior,
// and will not contain any / characters
set = this.globParts = set.map(function (s) {
return s.split(slashSplit)
})
this.debug(this.pattern, set)
// glob --> regexps
set = set.map(function (s, si, set) {
return s.map(this.parse, this)
}, this)
this.debug(this.pattern, set)
// filter out everything that didn't compile properly.
set = set.filter(function (s) {
return s.indexOf(false) === -1
})
this.debug(this.pattern, set)
this.set = set
}
Minimatch.prototype.parseNegate = parseNegate
function parseNegate () {
var pattern = this.pattern
var negate = false
var options = this.options
var negateOffset = 0
if (options.nonegate) return
for (var i = 0, l = pattern.length
; i < l && pattern.charAt(i) === '!'
; i++) {
negate = !negate
negateOffset++
}
if (negateOffset) this.pattern = pattern.substr(negateOffset)
this.negate = negate
}
// Brace expansion:
// a{b,c}d -> abd acd
// a{b,}c -> abc ac
// a{0..3}d -> a0d a1d a2d a3d
// a{b,c{d,e}f}g -> abg acdfg acefg
// a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg
//
// Invalid sets are not expanded.
// a{2..}b -> a{2..}b
// a{b}c -> a{b}c
minimatch.braceExpand = function (pattern, options) {
return braceExpand(pattern, options)
}
Minimatch.prototype.braceExpand = braceExpand
function braceExpand (pattern, options) {
if (!options) {
if (this instanceof Minimatch) {
options = this.options
} else {
options = {}
}
}
pattern = typeof pattern === 'undefined'
? this.pattern : pattern
if (typeof pattern === 'undefined') {
throw new Error('undefined pattern')
}
if (options.nobrace ||
!pattern.match(/\{.*\}/)) {
// shortcut. no need to expand.
return [pattern]
}
return expand(pattern)
}
// parse a component of the expanded set.
// At this point, no pattern may contain "/" in it
// so we're going to return a 2d array, where each entry is the full
// pattern, split on '/', and then turned into a regular expression.
// A regexp is made at the end which joins each array with an
// escaped /, and another full one which joins each regexp with |.
//
// Following the lead of Bash 4.1, note that "**" only has special meaning
// when it is the *only* thing in a path portion. Otherwise, any series
// of * is equivalent to a single *. Globstar behavior is enabled by
// default, and can be disabled by setting options.noglobstar.
Minimatch.prototype.parse = parse
var SUBPARSE = {}
function parse (pattern, isSub) {
var options = this.options
// shortcuts
if (!options.noglobstar && pattern === '**') return GLOBSTAR
if (pattern === '') return ''
var re = ''
var hasMagic = !!options.nocase
var escaping = false
// ? => one single character
var patternListStack = []
var plType
var stateChar
var inClass = false
var reClassStart = -1
var classStart = -1
// . and .. never match anything that doesn't start with .,
// even when options.dot is set.
var patternStart = pattern.charAt(0) === '.' ? '' // anything
// not (start or / followed by . or .. followed by / or end)
: options.dot ? '(?!(?:^|\\\/)\\.{1,2}(?:$|\\\/))'
: '(?!\\.)'
var self = this
function clearStateChar () {
if (stateChar) {
// we had some state-tracking character
// that wasn't consumed by this pass.
switch (stateChar) {
case '*':
re += star
hasMagic = true
break
case '?':
re += qmark
hasMagic = true
break
default:
re += '\\' + stateChar
break
}
self.debug('clearStateChar %j %j', stateChar, re)
stateChar = false
}
}
for (var i = 0, len = pattern.length, c
; (i < len) && (c = pattern.charAt(i))
; i++) {
this.debug('%s\t%s %s %j', pattern, i, re, c)
// skip over any that are escaped.
if (escaping && reSpecials[c]) {
re += '\\' + c
escaping = false
continue
}
switch (c) {
case '/':
// completely not allowed, even escaped.
// Should already be path-split by now.
return false
case '\\':
clearStateChar()
escaping = true
continue
// the various stateChar values
// for the "extglob" stuff.
case '?':
case '*':
case '+':
case '@':
case '!':
this.debug('%s\t%s %s %j <-- stateChar', pattern, i, re, c)
// all of those are literals inside a class, except that
// the glob [!a] means [^a] in regexp
if (inClass) {
this.debug(' in class')
if (c === '!' && i === classStart + 1) c = '^'
re += c
continue
}
// if we already have a stateChar, then it means
// that there was something like ** or +? in there.
// Handle the stateChar, then proceed with this one.
self.debug('call clearStateChar %j', stateChar)
clearStateChar()
stateChar = c
// if extglob is disabled, then +(asdf|foo) isn't a thing.
// just clear the statechar *now*, rather than even diving into
// the patternList stuff.
if (options.noext) clearStateChar()
continue
case '(':
if (inClass) {
re += '('
continue
}
if (!stateChar) {
re += '\\('
continue
}
plType = stateChar
patternListStack.push({ type: plType, start: i - 1, reStart: re.length })
// negation is (?:(?!js)[^/]*)
re += stateChar === '!' ? '(?:(?!' : '(?:'
this.debug('plType %j %j', stateChar, re)
stateChar = false
continue
case ')':
if (inClass || !patternListStack.length) {
re += '\\)'
continue
}
clearStateChar()
hasMagic = true
re += ')'
plType = patternListStack.pop().type
// negation is (?:(?!js)[^/]*)
// The others are (?:<pattern>)<type>
switch (plType) {
case '!':
re += '[^/]*?)'
break
case '?':
case '+':
case '*':
re += plType
break
case '@': break // the default anyway
}
continue
case '|':
if (inClass || !patternListStack.length || escaping) {
re += '\\|'
escaping = false
continue
}
clearStateChar()
re += '|'
continue
// these are mostly the same in regexp and glob
case '[':
// swallow any state-tracking char before the [
clearStateChar()
if (inClass) {
re += '\\' + c
continue
}
inClass = true
classStart = i
reClassStart = re.length
re += c
continue
case ']':
// a right bracket shall lose its special
// meaning and represent itself in
// a bracket expression if it occurs
// first in the list. -- POSIX.2 2.8.3.2
if (i === classStart + 1 || !inClass) {
re += '\\' + c
escaping = false
continue
}
// handle the case where we left a class open.
// "[z-a]" is valid, equivalent to "\[z-a\]"
if (inClass) {
// split where the last [ was, make sure we don't have
// an invalid re. if so, re-walk the contents of the
// would-be class to re-translate any characters that
// were passed through as-is
// TODO: It would probably be faster to determine this
// without a try/catch and a new RegExp, but it's tricky
// to do safely. For now, this is safe and works.
var cs = pattern.substring(classStart + 1, i)
try {
RegExp('[' + cs + ']')
} catch (er) {
// not a valid class!
var sp = this.parse(cs, SUBPARSE)
re = re.substr(0, reClassStart) + '\\[' + sp[0] + '\\]'
hasMagic = hasMagic || sp[1]
inClass = false
continue
}
}
// finish up the class.
hasMagic = true
inClass = false
re += c
continue
default:
// swallow any state char that wasn't consumed
clearStateChar()
if (escaping) {
// no need
escaping = false
} else if (reSpecials[c]
&& !(c === '^' && inClass)) {
re += '\\'
}
re += c
} // switch
} // for
// handle the case where we left a class open.
// "[abc" is valid, equivalent to "\[abc"
if (inClass) {
// split where the last [ was, and escape it
// this is a huge pita. We now have to re-walk
// the contents of the would-be class to re-translate
// any characters that were passed through as-is
cs = pattern.substr(classStart + 1)
sp = this.parse(cs, SUBPARSE)
re = re.substr(0, reClassStart) + '\\[' + sp[0]
hasMagic = hasMagic || sp[1]
}
// handle the case where we had a +( thing at the *end*
// of the pattern.
// each pattern list stack adds 3 chars, and we need to go through
// and escape any | chars that were passed through as-is for the regexp.
// Go through and escape them, taking care not to double-escape any
// | chars that were already escaped.
for (var pl = patternListStack.pop(); pl; pl = patternListStack.pop()) {
var tail = re.slice(pl.reStart + 3)
// maybe some even number of \, then maybe 1 \, followed by a |
tail = tail.replace(/((?:\\{2})*)(\\?)\|/g, function (_, $1, $2) {
if (!$2) {
// the | isn't already escaped, so escape it.
$2 = '\\'
}
// need to escape all those slashes *again*, without escaping the
// one that we need for escaping the | character. As it works out,
// escaping an even number of slashes can be done by simply repeating
// it exactly after itself. That's why this trick works.
//
// I am sorry that you have to see this.
return $1 + $1 + $2 + '|'
})
this.debug('tail=%j\n %s', tail, tail)
var t = pl.type === '*' ? star
: pl.type === '?' ? qmark
: '\\' + pl.type
hasMagic = true
re = re.slice(0, pl.reStart) + t + '\\(' + tail
}
// handle trailing things that only matter at the very end.
clearStateChar()
if (escaping) {
// trailing \\
re += '\\\\'
}
// only need to apply the nodot start if the re starts with
// something that could conceivably capture a dot
var addPatternStart = false
switch (re.charAt(0)) {
case '.':
case '[':
case '(': addPatternStart = true
}
// if the re is not "" at this point, then we need to make sure
// it doesn't match against an empty path part.
// Otherwise a/* will match a/, which it should not.
if (re !== '' && hasMagic) re = '(?=.)' + re
if (addPatternStart) re = patternStart + re
// parsing just a piece of a larger pattern.
if (isSub === SUBPARSE) {
return [re, hasMagic]
}
// skip the regexp for non-magical patterns
// unescape anything in it, though, so that it'll be
// an exact match against a file etc.
if (!hasMagic) {
return globUnescape(pattern)
}
var flags = options.nocase ? 'i' : ''
var regExp = new RegExp('^' + re + '$', flags)
regExp._glob = pattern
regExp._src = re
return regExp
}
minimatch.makeRe = function (pattern, options) {
return new Minimatch(pattern, options || {}).makeRe()
}
Minimatch.prototype.makeRe = makeRe
function makeRe () {
if (this.regexp || this.regexp === false) return this.regexp
// at this point, this.set is a 2d array of partial
// pattern strings, or "**".
//
// It's better to use .match(). This function shouldn't
// be used, really, but it's pretty convenient sometimes,
// when you just want to work with a regex.
var set = this.set
if (!set.length) {
this.regexp = false
return this.regexp
}
var options = this.options
var twoStar = options.noglobstar ? star
: options.dot ? twoStarDot
: twoStarNoDot
var flags = options.nocase ? 'i' : ''
var re = set.map(function (pattern) {
return pattern.map(function (p) {
return (p === GLOBSTAR) ? twoStar
: (typeof p === 'string') ? regExpEscape(p)
: p._src
}).join('\\\/')
}).join('|')
// must match entire pattern
// ending in a * or ** will make it less strict.
re = '^(?:' + re + ')$'
// can match anything, as long as it's not this.
if (this.negate) re = '^(?!' + re + ').*$'
try {
this.regexp = new RegExp(re, flags)
} catch (ex) {
this.regexp = false
}
return this.regexp
}
minimatch.match = function (list, pattern, options) {
options = options || {}
var mm = new Minimatch(pattern, options)
list = list.filter(function (f) {
return mm.match(f)
})
if (mm.options.nonull && !list.length) {
list.push(pattern)
}
return list
}
Minimatch.prototype.match = match
function match (f, partial) {
this.debug('match', f, this.pattern)
// short-circuit in the case of busted things.
// comments, etc.
if (this.comment) return false
if (this.empty) return f === ''
if (f === '/' && partial) return true
var options = this.options
// windows: need to use /, not \
if (path.sep !== '/') {
f = f.split(path.sep).join('/')
}
// treat the test path as a set of pathparts.
f = f.split(slashSplit)
this.debug(this.pattern, 'split', f)
// just ONE of the pattern sets in this.set needs to match
// in order for it to be valid. If negating, then just one
// match means that we have failed.
// Either way, return on the first hit.
var set = this.set
this.debug(this.pattern, 'set', set)
// Find the basename of the path by looking for the last non-empty segment
var filename
var i
for (i = f.length - 1; i >= 0; i--) {
filename = f[i]
if (filename) break
}
for (i = 0; i < set.length; i++) {
var pattern = set[i]
var file = f
if (options.matchBase && pattern.length === 1) {
file = [filename]
}
var hit = this.matchOne(file, pattern, partial)
if (hit) {
if (options.flipNegate) return true
return !this.negate
}
}
// didn't get any hits. this is success if it's a negative
// pattern, failure otherwise.
if (options.flipNegate) return false
return this.negate
}
// set partial to true to test if, for example,
// "/a/b" matches the start of "/*/b/*/d"
// Partial means, if you run out of file before you run
// out of pattern, then that's fine, as long as all
// the parts match.
Minimatch.prototype.matchOne = function (file, pattern, partial) {
var options = this.options
this.debug('matchOne',
{ 'this': this, file: file, pattern: pattern })
this.debug('matchOne', file.length, pattern.length)
for (var fi = 0,
pi = 0,
fl = file.length,
pl = pattern.length
; (fi < fl) && (pi < pl)
; fi++, pi++) {
this.debug('matchOne loop')
var p = pattern[pi]
var f = file[fi]
this.debug(pattern, p, f)
// should be impossible.
// some invalid regexp stuff in the set.
if (p === false) return false
if (p === GLOBSTAR) {
this.debug('GLOBSTAR', [pattern, p, f])
// "**"
// a/**/b/**/c would match the following:
// a/b/x/y/z/c
// a/x/y/z/b/c
// a/b/x/b/x/c
// a/b/c
// To do this, take the rest of the pattern after
// the **, and see if it would match the file remainder.
// If so, return success.
// If not, the ** "swallows" a segment, and try again.
// This is recursively awful.
//
// a/**/b/**/c matching a/b/x/y/z/c
// - a matches a
// - doublestar
// - matchOne(b/x/y/z/c, b/**/c)
// - b matches b
// - doublestar
// - matchOne(x/y/z/c, c) -> no
// - matchOne(y/z/c, c) -> no
// - matchOne(z/c, c) -> no
// - matchOne(c, c) yes, hit
var fr = fi
var pr = pi + 1
if (pr === pl) {
this.debug('** at the end')
// a ** at the end will just swallow the rest.
// We have found a match.
// however, it will not swallow /.x, unless
// options.dot is set.
// . and .. are *never* matched by **, for explosively
// exponential reasons.
for (; fi < fl; fi++) {
if (file[fi] === '.' || file[fi] === '..' ||
(!options.dot && file[fi].charAt(0) === '.')) return false
}
return true
}
// ok, let's see if we can swallow whatever we can.
while (fr < fl) {
var swallowee = file[fr]
this.debug('\nglobstar while', file, fr, pattern, pr, swallowee)
// XXX remove this slice. Just pass the start index.
if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) {
this.debug('globstar found match!', fr, fl, swallowee)
// found a match.
return true
} else {
// can't swallow "." or ".." ever.
// can only swallow ".foo" when explicitly asked.
if (swallowee === '.' || swallowee === '..' ||
(!options.dot && swallowee.charAt(0) === '.')) {
this.debug('dot detected!', file, fr, pattern, pr)
break
}
// ** swallows a segment, and continue.
this.debug('globstar swallow a segment, and continue')
fr++
}
}
// no match was found.
// However, in partial mode, we can't say this is necessarily over.
// If there's more *pattern* left, then
if (partial) {
// ran out of file
this.debug('\n>>> no match, partial?', file, fr, pattern, pr)
if (fr === fl) return true
}
return false
}
// something other than **
// non-magic patterns just have to match exactly
// patterns with magic have been turned into regexps.
var hit
if (typeof p === 'string') {
if (options.nocase) {
hit = f.toLowerCase() === p.toLowerCase()
} else {
hit = f === p
}
this.debug('string match', p, f, hit)
} else {
hit = f.match(p)
this.debug('pattern match', p, f, hit)
}
if (!hit) return false
}
// Note: ending in / means that we'll get a final ""
// at the end of the pattern. This can only match a
// corresponding "" at the end of the file.
// If the file ends in /, then it can only match a
// a pattern that ends in /, unless the pattern just
// doesn't have any more for it. But, a/b/ should *not*
// match "a/b/*", even though "" matches against the
// [^/]*? pattern, except in partial mode, where it might
// simply not be reached yet.
// However, a/b/ should still satisfy a/*
// now either we fell off the end of the pattern, or we're done.
if (fi === fl && pi === pl) {
// ran out of pattern and filename at the same time.
// an exact hit!
return true
} else if (fi === fl) {
// ran out of file, but still had pattern left.
// this is ok if we're doing the match as part of
// a glob fs traversal.
return partial
} else if (pi === pl) {
// ran out of pattern, still have file left.
// this is only acceptable if we're on the very last
// empty segment of a file with a trailing slash.
// a/* should match a/b/
var emptyFileEnd = (fi === fl - 1) && (file[fi] === '')
return emptyFileEnd
}
// should be unreachable.
throw new Error('wtf?')
}
// replace stuff like \* with *
function globUnescape (s) {
return s.replace(/\\(.)/g, '$1')
}
function regExpEscape (s) {
return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&')
}
},{"brace-expansion":2,"path":undefined}],2:[function(require,module,exports){
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 [];
var expansions = expand(escapeBraces(str));
return expansions.filter(identity).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) {
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]).map(embrace);
if (n.length === 1) {
var post = m.post.length
? expand(m.post)
: [''];
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)
: [''];
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) });
}
for (var j = 0; j < N.length; j++) {
for (var k = 0; k < post.length; k++) {
expansions.push([pre, N[j], post[k]].join(''))
}
}
return expansions;
}
},{"balanced-match":3,"concat-map":4}],3:[function(require,module,exports){
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;
}
}
},{}],4:[function(require,module,exports){
module.exports = function (xs, fn) {
var res = [];
for (var i = 0; i < xs.length; i++) {
var x = fn(xs[i], i);
if (Array.isArray(x)) res.push.apply(res, x);
else res.push(x);
}
return res;
};
},{}]},{},[1]);
module.exports = minimatch
minimatch.Minimatch = Minimatch
var path = { sep: '/' }
try {
path = require('path')
} catch (er) {}
var GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {}
var expand = require('brace-expansion')
// any single thing other than /
// don't need to escape / when using new RegExp()
var qmark = '[^/]'
// * => any number of characters
var star = qmark + '*?'
// ** when dots are allowed. Anything goes, except .. and .
// not (^ or / followed by one or two dots followed by $ or /),
// followed by anything, any number of times.
var twoStarDot = '(?:(?!(?:\\\/|^)(?:\\.{1,2})($|\\\/)).)*?'
// not a ^ or / followed by a dot,
// followed by anything, any number of times.
var twoStarNoDot = '(?:(?!(?:\\\/|^)\\.).)*?'
// characters that need to be escaped in RegExp.
var reSpecials = charSet('().*{}+?[]^$\\!')
// "abc" -> { a:true, b:true, c:true }
function charSet (s) {
return s.split('').reduce(function (set, c) {
set[c] = true
return set
}, {})
}
// normalizes slashes.
var slashSplit = /\/+/
minimatch.filter = filter
function filter (pattern, options) {
options = options || {}
return function (p, i, list) {
return minimatch(p, pattern, options)
}
}
function ext (a, b) {
a = a || {}
b = b || {}
var t = {}
Object.keys(b).forEach(function (k) {
t[k] = b[k]
})
Object.keys(a).forEach(function (k) {
t[k] = a[k]
})
return t
}
minimatch.defaults = function (def) {
if (!def || !Object.keys(def).length) return minimatch
var orig = minimatch
var m = function minimatch (p, pattern, options) {
return orig.minimatch(p, pattern, ext(def, options))
}
m.Minimatch = function Minimatch (pattern, options) {
return new orig.Minimatch(pattern, ext(def, options))
}
return m
}
Minimatch.defaults = function (def) {
if (!def || !Object.keys(def).length) return Minimatch
return minimatch.defaults(def).Minimatch
}
function minimatch (p, pattern, options) {
if (typeof pattern !== 'string') {
throw new TypeError('glob pattern string required')
}
if (!options) options = {}
// shortcut: comments match nothing.
if (!options.nocomment && pattern.charAt(0) === '#') {
return false
}
// "" only matches ""
if (pattern.trim() === '') return p === ''
return new Minimatch(pattern, options).match(p)
}
function Minimatch (pattern, options) {
if (!(this instanceof Minimatch)) {
return new Minimatch(pattern, options)
}
if (typeof pattern !== 'string') {
throw new TypeError('glob pattern string required')
}
if (!options) options = {}
pattern = pattern.trim()
// windows support: need to use /, not \
if (path.sep !== '/') {
pattern = pattern.split(path.sep).join('/')
}
this.options = options
this.set = []
this.pattern = pattern
this.regexp = null
this.negate = false
this.comment = false
this.empty = false
// make the set of regexps etc.
this.make()
}
Minimatch.prototype.debug = function () {}
Minimatch.prototype.make = make
function make () {
// don't do it more than once.
if (this._made) return
var pattern = this.pattern
var options = this.options
// empty patterns and comments match nothing.
if (!options.nocomment && pattern.charAt(0) === '#') {
this.comment = true
return
}
if (!pattern) {
this.empty = true
return
}
// step 1: figure out negation, etc.
this.parseNegate()
// step 2: expand braces
var set = this.globSet = this.braceExpand()
if (options.debug) this.debug = console.error
this.debug(this.pattern, set)
// step 3: now we have a set, so turn each one into a series of path-portion
// matching patterns.
// These will be regexps, except in the case of "**", which is
// set to the GLOBSTAR object for globstar behavior,
// and will not contain any / characters
set = this.globParts = set.map(function (s) {
return s.split(slashSplit)
})
this.debug(this.pattern, set)
// glob --> regexps
set = set.map(function (s, si, set) {
return s.map(this.parse, this)
}, this)
this.debug(this.pattern, set)
// filter out everything that didn't compile properly.
set = set.filter(function (s) {
return s.indexOf(false) === -1
})
this.debug(this.pattern, set)
this.set = set
}
Minimatch.prototype.parseNegate = parseNegate
function parseNegate () {
var pattern = this.pattern
var negate = false
var options = this.options
var negateOffset = 0
if (options.nonegate) return
for (var i = 0, l = pattern.length
; i < l && pattern.charAt(i) === '!'
; i++) {
negate = !negate
negateOffset++
}
if (negateOffset) this.pattern = pattern.substr(negateOffset)
this.negate = negate
}
// Brace expansion:
// a{b,c}d -> abd acd
// a{b,}c -> abc ac
// a{0..3}d -> a0d a1d a2d a3d
// a{b,c{d,e}f}g -> abg acdfg acefg
// a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg
//
// Invalid sets are not expanded.
// a{2..}b -> a{2..}b
// a{b}c -> a{b}c
minimatch.braceExpand = function (pattern, options) {
return braceExpand(pattern, options)
}
Minimatch.prototype.braceExpand = braceExpand
function braceExpand (pattern, options) {
if (!options) {
if (this instanceof Minimatch) {
options = this.options
} else {
options = {}
}
}
pattern = typeof pattern === 'undefined'
? this.pattern : pattern
if (typeof pattern === 'undefined') {
throw new Error('undefined pattern')
}
if (options.nobrace ||
!pattern.match(/\{.*\}/)) {
// shortcut. no need to expand.
return [pattern]
}
return expand(pattern)
}
// parse a component of the expanded set.
// At this point, no pattern may contain "/" in it
// so we're going to return a 2d array, where each entry is the full
// pattern, split on '/', and then turned into a regular expression.
// A regexp is made at the end which joins each array with an
// escaped /, and another full one which joins each regexp with |.
//
// Following the lead of Bash 4.1, note that "**" only has special meaning
// when it is the *only* thing in a path portion. Otherwise, any series
// of * is equivalent to a single *. Globstar behavior is enabled by
// default, and can be disabled by setting options.noglobstar.
Minimatch.prototype.parse = parse
var SUBPARSE = {}
function parse (pattern, isSub) {
var options = this.options
// shortcuts
if (!options.noglobstar && pattern === '**') return GLOBSTAR
if (pattern === '') return ''
var re = ''
var hasMagic = !!options.nocase
var escaping = false
// ? => one single character
var patternListStack = []
var plType
var stateChar
var inClass = false
var reClassStart = -1
var classStart = -1
// . and .. never match anything that doesn't start with .,
// even when options.dot is set.
var patternStart = pattern.charAt(0) === '.' ? '' // anything
// not (start or / followed by . or .. followed by / or end)
: options.dot ? '(?!(?:^|\\\/)\\.{1,2}(?:$|\\\/))'
: '(?!\\.)'
var self = this
function clearStateChar () {
if (stateChar) {
// we had some state-tracking character
// that wasn't consumed by this pass.
switch (stateChar) {
case '*':
re += star
hasMagic = true
break
case '?':
re += qmark
hasMagic = true
break
default:
re += '\\' + stateChar
break
}
self.debug('clearStateChar %j %j', stateChar, re)
stateChar = false
}
}
for (var i = 0, len = pattern.length, c
; (i < len) && (c = pattern.charAt(i))
; i++) {
this.debug('%s\t%s %s %j', pattern, i, re, c)
// skip over any that are escaped.
if (escaping && reSpecials[c]) {
re += '\\' + c
escaping = false
continue
}
switch (c) {
case '/':
// completely not allowed, even escaped.
// Should already be path-split by now.
return false
case '\\':
clearStateChar()
escaping = true
continue
// the various stateChar values
// for the "extglob" stuff.
case '?':
case '*':
case '+':
case '@':
case '!':
this.debug('%s\t%s %s %j <-- stateChar', pattern, i, re, c)
// all of those are literals inside a class, except that
// the glob [!a] means [^a] in regexp
if (inClass) {
this.debug(' in class')
if (c === '!' && i === classStart + 1) c = '^'
re += c
continue
}
// if we already have a stateChar, then it means
// that there was something like ** or +? in there.
// Handle the stateChar, then proceed with this one.
self.debug('call clearStateChar %j', stateChar)
clearStateChar()
stateChar = c
// if extglob is disabled, then +(asdf|foo) isn't a thing.
// just clear the statechar *now*, rather than even diving into
// the patternList stuff.
if (options.noext) clearStateChar()
continue
case '(':
if (inClass) {
re += '('
continue
}
if (!stateChar) {
re += '\\('
continue
}
plType = stateChar
patternListStack.push({ type: plType, start: i - 1, reStart: re.length })
// negation is (?:(?!js)[^/]*)
re += stateChar === '!' ? '(?:(?!' : '(?:'
this.debug('plType %j %j', stateChar, re)
stateChar = false
continue
case ')':
if (inClass || !patternListStack.length) {
re += '\\)'
continue
}
clearStateChar()
hasMagic = true
re += ')'
plType = patternListStack.pop().type
// negation is (?:(?!js)[^/]*)
// The others are (?:<pattern>)<type>
switch (plType) {
case '!':
re += '[^/]*?)'
break
case '?':
case '+':
case '*':
re += plType
break
case '@': break // the default anyway
}
continue
case '|':
if (inClass || !patternListStack.length || escaping) {
re += '\\|'
escaping = false
continue
}
clearStateChar()
re += '|'
continue
// these are mostly the same in regexp and glob
case '[':
// swallow any state-tracking char before the [
clearStateChar()
if (inClass) {
re += '\\' + c
continue
}
inClass = true
classStart = i
reClassStart = re.length
re += c
continue
case ']':
// a right bracket shall lose its special
// meaning and represent itself in
// a bracket expression if it occurs
// first in the list. -- POSIX.2 2.8.3.2
if (i === classStart + 1 || !inClass) {
re += '\\' + c
escaping = false
continue
}
// handle the case where we left a class open.
// "[z-a]" is valid, equivalent to "\[z-a\]"
if (inClass) {
// split where the last [ was, make sure we don't have
// an invalid re. if so, re-walk the contents of the
// would-be class to re-translate any characters that
// were passed through as-is
// TODO: It would probably be faster to determine this
// without a try/catch and a new RegExp, but it's tricky
// to do safely. For now, this is safe and works.
var cs = pattern.substring(classStart + 1, i)
try {
RegExp('[' + cs + ']')
} catch (er) {
// not a valid class!
var sp = this.parse(cs, SUBPARSE)
re = re.substr(0, reClassStart) + '\\[' + sp[0] + '\\]'
hasMagic = hasMagic || sp[1]
inClass = false
continue
}
}
// finish up the class.
hasMagic = true
inClass = false
re += c
continue
default:
// swallow any state char that wasn't consumed
clearStateChar()
if (escaping) {
// no need
escaping = false
} else if (reSpecials[c]
&& !(c === '^' && inClass)) {
re += '\\'
}
re += c
} // switch
} // for
// handle the case where we left a class open.
// "[abc" is valid, equivalent to "\[abc"
if (inClass) {
// split where the last [ was, and escape it
// this is a huge pita. We now have to re-walk
// the contents of the would-be class to re-translate
// any characters that were passed through as-is
cs = pattern.substr(classStart + 1)
sp = this.parse(cs, SUBPARSE)
re = re.substr(0, reClassStart) + '\\[' + sp[0]
hasMagic = hasMagic || sp[1]
}
// handle the case where we had a +( thing at the *end*
// of the pattern.
// each pattern list stack adds 3 chars, and we need to go through
// and escape any | chars that were passed through as-is for the regexp.
// Go through and escape them, taking care not to double-escape any
// | chars that were already escaped.
for (var pl = patternListStack.pop(); pl; pl = patternListStack.pop()) {
var tail = re.slice(pl.reStart + 3)
// maybe some even number of \, then maybe 1 \, followed by a |
tail = tail.replace(/((?:\\{2})*)(\\?)\|/g, function (_, $1, $2) {
if (!$2) {
// the | isn't already escaped, so escape it.
$2 = '\\'
}
// need to escape all those slashes *again*, without escaping the
// one that we need for escaping the | character. As it works out,
// escaping an even number of slashes can be done by simply repeating
// it exactly after itself. That's why this trick works.
//
// I am sorry that you have to see this.
return $1 + $1 + $2 + '|'
})
this.debug('tail=%j\n %s', tail, tail)
var t = pl.type === '*' ? star
: pl.type === '?' ? qmark
: '\\' + pl.type
hasMagic = true
re = re.slice(0, pl.reStart) + t + '\\(' + tail
}
// handle trailing things that only matter at the very end.
clearStateChar()
if (escaping) {
// trailing \\
re += '\\\\'
}
// only need to apply the nodot start if the re starts with
// something that could conceivably capture a dot
var addPatternStart = false
switch (re.charAt(0)) {
case '.':
case '[':
case '(': addPatternStart = true
}
// if the re is not "" at this point, then we need to make sure
// it doesn't match against an empty path part.
// Otherwise a/* will match a/, which it should not.
if (re !== '' && hasMagic) re = '(?=.)' + re
if (addPatternStart) re = patternStart + re
// parsing just a piece of a larger pattern.
if (isSub === SUBPARSE) {
return [re, hasMagic]
}
// skip the regexp for non-magical patterns
// unescape anything in it, though, so that it'll be
// an exact match against a file etc.
if (!hasMagic) {
return globUnescape(pattern)
}
var flags = options.nocase ? 'i' : ''
var regExp = new RegExp('^' + re + '$', flags)
regExp._glob = pattern
regExp._src = re
return regExp
}
minimatch.makeRe = function (pattern, options) {
return new Minimatch(pattern, options || {}).makeRe()
}
Minimatch.prototype.makeRe = makeRe
function makeRe () {
if (this.regexp || this.regexp === false) return this.regexp
// at this point, this.set is a 2d array of partial
// pattern strings, or "**".
//
// It's better to use .match(). This function shouldn't
// be used, really, but it's pretty convenient sometimes,
// when you just want to work with a regex.
var set = this.set
if (!set.length) {
this.regexp = false
return this.regexp
}
var options = this.options
var twoStar = options.noglobstar ? star
: options.dot ? twoStarDot
: twoStarNoDot
var flags = options.nocase ? 'i' : ''
var re = set.map(function (pattern) {
return pattern.map(function (p) {
return (p === GLOBSTAR) ? twoStar
: (typeof p === 'string') ? regExpEscape(p)
: p._src
}).join('\\\/')
}).join('|')
// must match entire pattern
// ending in a * or ** will make it less strict.
re = '^(?:' + re + ')$'
// can match anything, as long as it's not this.
if (this.negate) re = '^(?!' + re + ').*$'
try {
this.regexp = new RegExp(re, flags)
} catch (ex) {
this.regexp = false
}
return this.regexp
}
minimatch.match = function (list, pattern, options) {
options = options || {}
var mm = new Minimatch(pattern, options)
list = list.filter(function (f) {
return mm.match(f)
})
if (mm.options.nonull && !list.length) {
list.push(pattern)
}
return list
}
Minimatch.prototype.match = match
function match (f, partial) {
this.debug('match', f, this.pattern)
// short-circuit in the case of busted things.
// comments, etc.
if (this.comment) return false
if (this.empty) return f === ''
if (f === '/' && partial) return true
var options = this.options
// windows: need to use /, not \
if (path.sep !== '/') {
f = f.split(path.sep).join('/')
}
// treat the test path as a set of pathparts.
f = f.split(slashSplit)
this.debug(this.pattern, 'split', f)
// just ONE of the pattern sets in this.set needs to match
// in order for it to be valid. If negating, then just one
// match means that we have failed.
// Either way, return on the first hit.
var set = this.set
this.debug(this.pattern, 'set', set)
// Find the basename of the path by looking for the last non-empty segment
var filename
var i
for (i = f.length - 1; i >= 0; i--) {
filename = f[i]
if (filename) break
}
for (i = 0; i < set.length; i++) {
var pattern = set[i]
var file = f
if (options.matchBase && pattern.length === 1) {
file = [filename]
}
var hit = this.matchOne(file, pattern, partial)
if (hit) {
if (options.flipNegate) return true
return !this.negate
}
}
// didn't get any hits. this is success if it's a negative
// pattern, failure otherwise.
if (options.flipNegate) return false
return this.negate
}
// set partial to true to test if, for example,
// "/a/b" matches the start of "/*/b/*/d"
// Partial means, if you run out of file before you run
// out of pattern, then that's fine, as long as all
// the parts match.
Minimatch.prototype.matchOne = function (file, pattern, partial) {
var options = this.options
this.debug('matchOne',
{ 'this': this, file: file, pattern: pattern })
this.debug('matchOne', file.length, pattern.length)
for (var fi = 0,
pi = 0,
fl = file.length,
pl = pattern.length
; (fi < fl) && (pi < pl)
; fi++, pi++) {
this.debug('matchOne loop')
var p = pattern[pi]
var f = file[fi]
this.debug(pattern, p, f)
// should be impossible.
// some invalid regexp stuff in the set.
if (p === false) return false
if (p === GLOBSTAR) {
this.debug('GLOBSTAR', [pattern, p, f])
// "**"
// a/**/b/**/c would match the following:
// a/b/x/y/z/c
// a/x/y/z/b/c
// a/b/x/b/x/c
// a/b/c
// To do this, take the rest of the pattern after
// the **, and see if it would match the file remainder.
// If so, return success.
// If not, the ** "swallows" a segment, and try again.
// This is recursively awful.
//
// a/**/b/**/c matching a/b/x/y/z/c
// - a matches a
// - doublestar
// - matchOne(b/x/y/z/c, b/**/c)
// - b matches b
// - doublestar
// - matchOne(x/y/z/c, c) -> no
// - matchOne(y/z/c, c) -> no
// - matchOne(z/c, c) -> no
// - matchOne(c, c) yes, hit
var fr = fi
var pr = pi + 1
if (pr === pl) {
this.debug('** at the end')
// a ** at the end will just swallow the rest.
// We have found a match.
// however, it will not swallow /.x, unless
// options.dot is set.
// . and .. are *never* matched by **, for explosively
// exponential reasons.
for (; fi < fl; fi++) {
if (file[fi] === '.' || file[fi] === '..' ||
(!options.dot && file[fi].charAt(0) === '.')) return false
}
return true
}
// ok, let's see if we can swallow whatever we can.
while (fr < fl) {
var swallowee = file[fr]
this.debug('\nglobstar while', file, fr, pattern, pr, swallowee)
// XXX remove this slice. Just pass the start index.
if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) {
this.debug('globstar found match!', fr, fl, swallowee)
// found a match.
return true
} else {
// can't swallow "." or ".." ever.
// can only swallow ".foo" when explicitly asked.
if (swallowee === '.' || swallowee === '..' ||
(!options.dot && swallowee.charAt(0) === '.')) {
this.debug('dot detected!', file, fr, pattern, pr)
break
}
// ** swallows a segment, and continue.
this.debug('globstar swallow a segment, and continue')
fr++
}
}
// no match was found.
// However, in partial mode, we can't say this is necessarily over.
// If there's more *pattern* left, then
if (partial) {
// ran out of file
this.debug('\n>>> no match, partial?', file, fr, pattern, pr)
if (fr === fl) return true
}
return false
}
// something other than **
// non-magic patterns just have to match exactly
// patterns with magic have been turned into regexps.
var hit
if (typeof p === 'string') {
if (options.nocase) {
hit = f.toLowerCase() === p.toLowerCase()
} else {
hit = f === p
}
this.debug('string match', p, f, hit)
} else {
hit = f.match(p)
this.debug('pattern match', p, f, hit)
}
if (!hit) return false
}
// Note: ending in / means that we'll get a final ""
// at the end of the pattern. This can only match a
// corresponding "" at the end of the file.
// If the file ends in /, then it can only match a
// a pattern that ends in /, unless the pattern just
// doesn't have any more for it. But, a/b/ should *not*
// match "a/b/*", even though "" matches against the
// [^/]*? pattern, except in partial mode, where it might
// simply not be reached yet.
// However, a/b/ should still satisfy a/*
// now either we fell off the end of the pattern, or we're done.
if (fi === fl && pi === pl) {
// ran out of pattern and filename at the same time.
// an exact hit!
return true
} else if (fi === fl) {
// ran out of file, but still had pattern left.
// this is ok if we're doing the match as part of
// a glob fs traversal.
return partial
} else if (pi === pl) {
// ran out of pattern, still have file left.
// this is only acceptable if we're on the very last
// empty segment of a file with a trailing slash.
// a/* should match a/b/
var emptyFileEnd = (fi === fl - 1) && (file[fi] === '')
return emptyFileEnd
}
// should be unreachable.
throw new Error('wtf?')
}
// replace stuff like \* with *
function globUnescape (s) {
return s.replace(/\\(.)/g, '$1')
}
function regExpEscape (s) {
return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&')
}
# 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
}
}
var wrappy = require('wrappy')
module.exports = wrappy(once)
once.proto = once(function () {
Object.defineProperty(Function.prototype, 'once', {
value: function () {
return once(this)
},
configurable: true
})
})
function once (fn) {
var f = function () {
if (f.called) return f.value
f.called = true
return f.value = fn.apply(this, arguments)
}
f.called = false
return f
}
{
"name": "once",
"version": "1.3.2",
"description": "Run a function exactly one time",
"main": "once.js",
"directories": {
"test": "test"
},
"dependencies": {
"wrappy": "1"
},
"devDependencies": {
"tap": "~0.3.0"
},
"scripts": {
"test": "tap test/*.js"
},
"repository": {
"type": "git",
"url": "git://github.com/isaacs/once.git"
},
"keywords": [
"once",
"function",
"one",
"single"
],
"author": {
"name": "Isaac Z. Schlueter",
"email": "i@izs.me",
"url": "http://blog.izs.me/"
},
"license": "ISC",
"gitHead": "e35eed5a7867574e2bf2260a1ba23970958b22f2",
"bugs": {
"url": "https://github.com/isaacs/once/issues"
},
"homepage": "https://github.com/isaacs/once#readme",
"_id": "once@1.3.2",
"_shasum": "d8feeca93b039ec1dcdee7741c92bdac5e28081b",
"_from": "once@>=1.3.0 <2.0.0",
"_npmVersion": "2.9.1",
"_nodeVersion": "2.0.0",
"_npmUser": {
"name": "isaacs",
"email": "isaacs@npmjs.com"
},
"dist": {
"shasum": "d8feeca93b039ec1dcdee7741c92bdac5e28081b",
"tarball": "http://registry.npmjs.org/once/-/once-1.3.2.tgz"
},
"maintainers": [
{
"name": "isaacs",
"email": "i@izs.me"
}
],
"_resolved": "https://registry.npmjs.org/once/-/once-1.3.2.tgz",
"readme": "ERROR: No README data found!"
}
var test = require('tap').test
var once = require('../once.js')
test('once', function (t) {
var f = 0
function fn (g) {
t.equal(f, 0)
f ++
return f + g + this
}
fn.ownProperty = {}
var foo = once(fn)
t.equal(fn.ownProperty, foo.ownProperty)
t.notOk(foo.called)
for (var i = 0; i < 1E3; i++) {
t.same(f, i === 0 ? 0 : 1)
var g = foo.call(1, 1)
t.ok(foo.called)
t.same(g, 3)
t.same(f, 1)
}
t.end()
})
'use strict';
function posix(path) {
return path.charAt(0) === '/';
};
function win32(path) {
// https://github.com/joyent/node/blob/b3fcc245fb25539909ef1d5eaa01dbf92e168633/lib/path.js#L56
var splitDeviceRe = /^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/]+[^\\\/]+)?([\\\/])?([\s\S]*?)$/;
var result = splitDeviceRe.exec(path);
var device = result[1] || '';
var isUnc = !!device && device.charAt(1) !== ':';
// UNC paths are always absolute
return !!result[2] || isUnc;
};
module.exports = process.platform === 'win32' ? win32 : posix;
module.exports.posix = posix;
module.exports.win32 = win32;
The MIT License (MIT)
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
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.
{
"name": "path-is-absolute",
"version": "1.0.0",
"description": "Node.js 0.12 path.isAbsolute() ponyfill",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/sindresorhus/path-is-absolute"
},
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
},
"engines": {
"node": ">=0.10.0"
},
"scripts": {
"test": "node test.js"
},
"files": [
"index.js"
],
"keywords": [
"path",
"paths",
"file",
"dir",
"absolute",
"isabsolute",
"is-absolute",
"built-in",
"util",
"utils",
"core",
"ponyfill",
"polyfill",
"shim",
"is",
"detect",
"check"
],
"gitHead": "7a76a0c9f2263192beedbe0a820e4d0baee5b7a1",
"bugs": {
"url": "https://github.com/sindresorhus/path-is-absolute/issues"
},
"homepage": "https://github.com/sindresorhus/path-is-absolute",
"_id": "path-is-absolute@1.0.0",
"_shasum": "263dada66ab3f2fb10bf7f9d24dd8f3e570ef912",
"_from": "path-is-absolute@>=1.0.0 <2.0.0",
"_npmVersion": "2.5.1",
"_nodeVersion": "0.12.0",
"_npmUser": {
"name": "sindresorhus",
"email": "sindresorhus@gmail.com"
},
"maintainers": [
{
"name": "sindresorhus",
"email": "sindresorhus@gmail.com"
}
],
"dist": {
"shasum": "263dada66ab3f2fb10bf7f9d24dd8f3e570ef912",
"tarball": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.0.tgz"
},
"directories": {},
"_resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.0.tgz",
"readme": "ERROR: No README data found!"
}
# path-is-absolute [![Build Status](https://travis-ci.org/sindresorhus/path-is-absolute.svg?branch=master)](https://travis-ci.org/sindresorhus/path-is-absolute)
> Node.js 0.12 [`path.isAbsolute()`](http://nodejs.org/api/path.html#path_path_isabsolute_path) ponyfill
> Ponyfill: A polyfill that doesn't overwrite the native method
## Install
```
$ npm install --save path-is-absolute
```
## Usage
```js
var pathIsAbsolute = require('path-is-absolute');
// Linux
pathIsAbsolute('/home/foo');
//=> true
// Windows
pathIsAbsolute('C:/Users/');
//=> true
// Any OS
pathIsAbsolute.posix('/home/foo');
//=> true
```
## API
See the [`path.isAbsolute()` docs](http://nodejs.org/api/path.html#path_path_isabsolute_path).
### pathIsAbsolute(path)
### pathIsAbsolute.posix(path)
The Posix specific version.
### pathIsAbsolute.win32(path)
The Windows specific version.
## License
MIT © [Sindre Sorhus](http://sindresorhus.com)
{
"author": {
"name": "Isaac Z. Schlueter",
"email": "i@izs.me",
"url": "http://blog.izs.me/"
},
"name": "glob",
"description": "a little globber",
"version": "5.0.10",
"repository": {
"type": "git",
"url": "git://github.com/isaacs/node-glob.git"
},
"main": "glob.js",
"files": [
"glob.js",
"sync.js",
"common.js"
],
"engines": {
"node": "*"
},
"dependencies": {
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^2.0.1",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
},
"devDependencies": {
"mkdirp": "0",
"rimraf": "^2.2.8",
"tap": "^1.1.4",
"tick": "0.0.6"
},
"scripts": {
"prepublish": "npm run benchclean",
"profclean": "rm -f v8.log profile.txt",
"test": "tap test/*.js --cov",
"test-regen": "npm run profclean && TEST_REGEN=1 node test/00-setup.js",
"bench": "bash benchmark.sh",
"prof": "bash prof.sh && cat profile.txt",
"benchclean": "bash benchclean.sh"
},
"license": "ISC",
"gitHead": "e3cdccc0e295c2e1d5f40cf74c73ea17a8319c5c",
"bugs": {
"url": "https://github.com/isaacs/node-glob/issues"
},
"homepage": "https://github.com/isaacs/node-glob#readme",
"_id": "glob@5.0.10",
"_shasum": "3ee350319f31f352cef6899a48f6b6b7834c6899",
"_from": "glob@>=5.0.10 <6.0.0",
"_npmVersion": "2.10.1",
"_nodeVersion": "2.0.1",
"_npmUser": {
"name": "isaacs",
"email": "isaacs@npmjs.com"
},
"dist": {
"shasum": "3ee350319f31f352cef6899a48f6b6b7834c6899",
"tarball": "http://registry.npmjs.org/glob/-/glob-5.0.10.tgz"
},
"maintainers": [
{
"name": "isaacs",
"email": "i@izs.me"
}
],
"directories": {},
"_resolved": "https://registry.npmjs.org/glob/-/glob-5.0.10.tgz",
"readme": "ERROR: No README data found!"
}
module.exports = globSync
globSync.GlobSync = GlobSync
var fs = require('fs')
var minimatch = require('minimatch')
var Minimatch = minimatch.Minimatch
var Glob = require('./glob.js').Glob
var util = require('util')
var path = require('path')
var assert = require('assert')
var isAbsolute = require('path-is-absolute')
var common = require('./common.js')
var alphasort = common.alphasort
var alphasorti = common.alphasorti
var setopts = common.setopts
var ownProp = common.ownProp
var childrenIgnored = common.childrenIgnored
function globSync (pattern, options) {
if (typeof options === 'function' || arguments.length === 3)
throw new TypeError('callback provided to sync glob\n'+
'See: https://github.com/isaacs/node-glob/issues/167')
return new GlobSync(pattern, options).found
}
function GlobSync (pattern, options) {
if (!pattern)
throw new Error('must provide pattern')
if (typeof options === 'function' || arguments.length === 3)
throw new TypeError('callback provided to sync glob\n'+
'See: https://github.com/isaacs/node-glob/issues/167')
if (!(this instanceof GlobSync))
return new GlobSync(pattern, options)
setopts(this, pattern, options)
if (this.noprocess)
return this
var n = this.minimatch.set.length
this.matches = new Array(n)
for (var i = 0; i < n; i ++) {
this._process(this.minimatch.set[i], i, false)
}
this._finish()
}
GlobSync.prototype._finish = function () {
assert(this instanceof GlobSync)
if (this.realpath) {
var self = this
this.matches.forEach(function (matchset, index) {
var set = self.matches[index] = Object.create(null)
for (var p in matchset) {
try {
p = self._makeAbs(p)
var real = fs.realpathSync(p, this.realpathCache)
set[real] = true
} catch (er) {
if (er.syscall === 'stat')
set[self._makeAbs(p)] = true
else
throw er
}
}
})
}
common.finish(this)
}
GlobSync.prototype._process = function (pattern, index, inGlobStar) {
assert(this instanceof GlobSync)
// Get the first [n] parts of pattern that are all strings.
var n = 0
while (typeof pattern[n] === 'string') {
n ++
}
// now n is the index of the first one that is *not* a string.
// See if there's anything else
var prefix
switch (n) {
// if not, then this is rather simple
case pattern.length:
this._processSimple(pattern.join('/'), index)
return
case 0:
// pattern *starts* with some non-trivial item.
// going to readdir(cwd), but not include the prefix in matches.
prefix = null
break
default:
// pattern has some string bits in the front.
// whatever it starts with, whether that's 'absolute' like /foo/bar,
// or 'relative' like '../baz'
prefix = pattern.slice(0, n).join('/')
break
}
var remain = pattern.slice(n)
// get the list of entries.
var read
if (prefix === null)
read = '.'
else if (isAbsolute(prefix) || isAbsolute(pattern.join('/'))) {
if (!prefix || !isAbsolute(prefix))
prefix = '/' + prefix
read = prefix
} else
read = prefix
var abs = this._makeAbs(read)
//if ignored, skip processing
if (childrenIgnored(this, read))
return
var isGlobStar = remain[0] === minimatch.GLOBSTAR
if (isGlobStar)
this._processGlobStar(prefix, read, abs, remain, index, inGlobStar)
else
this._processReaddir(prefix, read, abs, remain, index, inGlobStar)
}
GlobSync.prototype._processReaddir = function (prefix, read, abs, remain, index, inGlobStar) {
var entries = this._readdir(abs, inGlobStar)
// if the abs isn't a dir, then nothing can match!
if (!entries)
return
// It will only match dot entries if it starts with a dot, or if
// dot is set. Stuff like @(.foo|.bar) isn't allowed.
var pn = remain[0]
var negate = !!this.minimatch.negate
var rawGlob = pn._glob
var dotOk = this.dot || rawGlob.charAt(0) === '.'
var matchedEntries = []
for (var i = 0; i < entries.length; i++) {
var e = entries[i]
if (e.charAt(0) !== '.' || dotOk) {
var m
if (negate && !prefix) {
m = !e.match(pn)
} else {
m = e.match(pn)
}
if (m)
matchedEntries.push(e)
}
}
var len = matchedEntries.length
// If there are no matched entries, then nothing matches.
if (len === 0)
return
// if this is the last remaining pattern bit, then no need for
// an additional stat *unless* the user has specified mark or
// stat explicitly. We know they exist, since readdir returned
// them.
if (remain.length === 1 && !this.mark && !this.stat) {
if (!this.matches[index])
this.matches[index] = Object.create(null)
for (var i = 0; i < len; i ++) {
var e = matchedEntries[i]
if (prefix) {
if (prefix.slice(-1) !== '/')
e = prefix + '/' + e
else
e = prefix + e
}
if (e.charAt(0) === '/' && !this.nomount) {
e = path.join(this.root, e)
}
this.matches[index][e] = true
}
// This was the last one, and no stats were needed
return
}
// now test all matched entries as stand-ins for that part
// of the pattern.
remain.shift()
for (var i = 0; i < len; i ++) {
var e = matchedEntries[i]
var newPattern
if (prefix)
newPattern = [prefix, e]
else
newPattern = [e]
this._process(newPattern.concat(remain), index, inGlobStar)
}
}
GlobSync.prototype._emitMatch = function (index, e) {
var abs = this._makeAbs(e)
if (this.mark)
e = this._mark(e)
if (this.matches[index][e])
return
if (this.nodir) {
var c = this.cache[this._makeAbs(e)]
if (c === 'DIR' || Array.isArray(c))
return
}
this.matches[index][e] = true
if (this.stat)
this._stat(e)
}
GlobSync.prototype._readdirInGlobStar = function (abs) {
// follow all symlinked directories forever
// just proceed as if this is a non-globstar situation
if (this.follow)
return this._readdir(abs, false)
var entries
var lstat
var stat
try {
lstat = fs.lstatSync(abs)
} catch (er) {
// lstat failed, doesn't exist
return null
}
var isSym = lstat.isSymbolicLink()
this.symlinks[abs] = isSym
// If it's not a symlink or a dir, then it's definitely a regular file.
// don't bother doing a readdir in that case.
if (!isSym && !lstat.isDirectory())
this.cache[abs] = 'FILE'
else
entries = this._readdir(abs, false)
return entries
}
GlobSync.prototype._readdir = function (abs, inGlobStar) {
var entries
if (inGlobStar && !ownProp(this.symlinks, abs))
return this._readdirInGlobStar(abs)
if (ownProp(this.cache, abs)) {
var c = this.cache[abs]
if (!c || c === 'FILE')
return null
if (Array.isArray(c))
return c
}
try {
return this._readdirEntries(abs, fs.readdirSync(abs))
} catch (er) {
this._readdirError(abs, er)
return null
}
}
GlobSync.prototype._readdirEntries = function (abs, entries) {
// if we haven't asked to stat everything, then just
// assume that everything in there exists, so we can avoid
// having to stat it a second time.
if (!this.mark && !this.stat) {
for (var i = 0; i < entries.length; i ++) {
var e = entries[i]
if (abs === '/')
e = abs + e
else
e = abs + '/' + e
this.cache[e] = true
}
}
this.cache[abs] = entries
// mark and cache dir-ness
return entries
}
GlobSync.prototype._readdirError = function (f, er) {
// handle errors, and cache the information
switch (er.code) {
case 'ENOTDIR': // totally normal. means it *does* exist.
this.cache[this._makeAbs(f)] = 'FILE'
break
case 'ENOENT': // not terribly unusual
case 'ELOOP':
case 'ENAMETOOLONG':
case 'UNKNOWN':
this.cache[this._makeAbs(f)] = false
break
default: // some unusual error. Treat as failure.
this.cache[this._makeAbs(f)] = false
if (this.strict)
throw er
if (!this.silent)
console.error('glob error', er)
break
}
}
GlobSync.prototype._processGlobStar = function (prefix, read, abs, remain, index, inGlobStar) {
var entries = this._readdir(abs, inGlobStar)
// no entries means not a dir, so it can never have matches
// foo.txt/** doesn't match foo.txt
if (!entries)
return
// test without the globstar, and with every child both below
// and replacing the globstar.
var remainWithoutGlobStar = remain.slice(1)
var gspref = prefix ? [ prefix ] : []
var noGlobStar = gspref.concat(remainWithoutGlobStar)
// the noGlobStar pattern exits the inGlobStar state
this._process(noGlobStar, index, false)
var len = entries.length
var isSym = this.symlinks[abs]
// If it's a symlink, and we're in a globstar, then stop
if (isSym && inGlobStar)
return
for (var i = 0; i < len; i++) {
var e = entries[i]
if (e.charAt(0) === '.' && !this.dot)
continue
// these two cases enter the inGlobStar state
var instead = gspref.concat(entries[i], remainWithoutGlobStar)
this._process(instead, index, true)
var below = gspref.concat(entries[i], remain)
this._process(below, index, true)
}
}
GlobSync.prototype._processSimple = function (prefix, index) {
// XXX review this. Shouldn't it be doing the mounting etc
// before doing stat? kinda weird?
var exists = this._stat(prefix)
if (!this.matches[index])
this.matches[index] = Object.create(null)
// If it doesn't exist, then just mark the lack of results
if (!exists)
return
if (prefix && isAbsolute(prefix) && !this.nomount) {
var trail = /[\/\\]$/.test(prefix)
if (prefix.charAt(0) === '/') {
prefix = path.join(this.root, prefix)
} else {
prefix = path.resolve(this.root, prefix)
if (trail)
prefix += '/'
}
}
if (process.platform === 'win32')
prefix = prefix.replace(/\\/g, '/')
// Mark this as a match
this.matches[index][prefix] = true
}
// Returns either 'DIR', 'FILE', or false
GlobSync.prototype._stat = function (f) {
var abs = this._makeAbs(f)
var needDir = f.slice(-1) === '/'
if (f.length > this.maxLength)
return false
if (!this.stat && ownProp(this.cache, abs)) {
var c = this.cache[abs]
if (Array.isArray(c))
c = 'DIR'
// It exists, but maybe not how we need it
if (!needDir || c === 'DIR')
return c
if (needDir && c === 'FILE')
return false
// otherwise we have to stat, because maybe c=true
// if we know it exists, but not what it is.
}
var exists
var stat = this.statCache[abs]
if (!stat) {
var lstat
try {
lstat = fs.lstatSync(abs)
} catch (er) {
return false
}
if (lstat.isSymbolicLink()) {
try {
stat = fs.statSync(abs)
} catch (er) {
stat = lstat
}
} else {
stat = lstat
}
}
this.statCache[abs] = stat
var c = stat.isDirectory() ? 'DIR' : 'FILE'
this.cache[abs] = this.cache[abs] || c
if (needDir && c !== 'DIR')
return false
return c
}
GlobSync.prototype._mark = function (p) {
return common.mark(this, p)
}
GlobSync.prototype._makeAbs = function (f) {
return common.makeAbs(this, f)
}
......@@ -25,6 +25,6 @@
Note: it does not work if the --shared option was used to create the project.
*/
var VERSION="3.8.0"
var VERSION="3.9.1"
console.log(VERSION);
/*
*
* 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.
*
*/
/**
* Creates a gap bridge iframe used to notify the native code about queued
* commands.
*/
var cordova = require('cordova'),
channel = require('cordova/channel'),
utils = require('cordova/utils'),
base64 = require('cordova/base64'),
// XHR mode does not work on iOS 4.2.
// XHR mode's main advantage is working around a bug in -webkit-scroll, which
// doesn't exist only on iOS 5.x devices.
// IFRAME_NAV is the fastest.
// IFRAME_HASH could be made to enable synchronous bridge calls if we wanted this feature.
jsToNativeModes = {
IFRAME_NAV: 0, // Default. Uses a new iframe for each poke.
// XHR bridge appears to be flaky sometimes: CB-3900, CB-3359, CB-5457, CB-4970, CB-4998, CB-5134
XHR_NO_PAYLOAD: 1, // About the same speed as IFRAME_NAV. Performance not about the same as IFRAME_NAV, but more variable.
XHR_WITH_PAYLOAD: 2, // Flakey, and not as performant
XHR_OPTIONAL_PAYLOAD: 3, // Flakey, and not as performant
IFRAME_HASH_NO_PAYLOAD: 4, // Not fully baked. A bit faster than IFRAME_NAV, but risks jank since poke happens synchronously.
IFRAME_HASH_WITH_PAYLOAD: 5, // Slower than no payload. Maybe since it has to be URI encoded / decoded.
WK_WEBVIEW_BINDING: 6 // Only way that works for WKWebView :)
},
bridgeMode,
execIframe,
execHashIframe,
hashToggle = 1,
execXhr,
requestCount = 0,
vcHeaderValue = null,
commandQueue = [], // Contains pending JS->Native messages.
isInContextOfEvalJs = 0,
failSafeTimerId = 0;
function shouldBundleCommandJson() {
if (bridgeMode === jsToNativeModes.XHR_WITH_PAYLOAD) {
return true;
}
if (bridgeMode === jsToNativeModes.XHR_OPTIONAL_PAYLOAD) {
var payloadLength = 0;
for (var i = 0; i < commandQueue.length; ++i) {
payloadLength += commandQueue[i].length;
}
// The value here was determined using the benchmark within CordovaLibApp on an iPad 3.
return payloadLength < 4500;
}
return false;
}
function massageArgsJsToNative(args) {
if (!args || utils.typeName(args) != 'Array') {
return args;
}
var ret = [];
args.forEach(function(arg, i) {
if (utils.typeName(arg) == 'ArrayBuffer') {
ret.push({
'CDVType': 'ArrayBuffer',
'data': base64.fromArrayBuffer(arg)
});
} else {
ret.push(arg);
}
});
return ret;
}
function massageMessageNativeToJs(message) {
if (message.CDVType == 'ArrayBuffer') {
var stringToArrayBuffer = function(str) {
var ret = new Uint8Array(str.length);
for (var i = 0; i < str.length; i++) {
ret[i] = str.charCodeAt(i);
}
return ret.buffer;
};
var base64ToArrayBuffer = function(b64) {
return stringToArrayBuffer(atob(b64));
};
message = base64ToArrayBuffer(message.data);
}
return message;
}
function convertMessageToArgsNativeToJs(message) {
var args = [];
if (!message || !message.hasOwnProperty('CDVType')) {
args.push(message);
} else if (message.CDVType == 'MultiPart') {
message.messages.forEach(function(e) {
args.push(massageMessageNativeToJs(e));
});
} else {
args.push(massageMessageNativeToJs(message));
}
return args;
}
function iOSExec() {
if (bridgeMode === undefined) {
bridgeMode = jsToNativeModes.IFRAME_NAV;
}
if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.cordova && window.webkit.messageHandlers.cordova.postMessage) {
bridgeMode = jsToNativeModes.WK_WEBVIEW_BINDING;
}
var successCallback, failCallback, service, action, actionArgs, splitCommand;
var callbackId = null;
if (typeof arguments[0] !== "string") {
// FORMAT ONE
successCallback = arguments[0];
failCallback = arguments[1];
service = arguments[2];
action = arguments[3];
actionArgs = arguments[4];
// Since we need to maintain backwards compatibility, we have to pass
// an invalid callbackId even if no callback was provided since plugins
// will be expecting it. The Cordova.exec() implementation allocates
// an invalid callbackId and passes it even if no callbacks were given.
callbackId = 'INVALID';
} else {
// FORMAT TWO, REMOVED
try {
splitCommand = arguments[0].split(".");
action = splitCommand.pop();
service = splitCommand.join(".");
actionArgs = Array.prototype.splice.call(arguments, 1);
console.log('The old format of this exec call has been removed (deprecated since 2.1). Change to: ' +
"cordova.exec(null, null, \"" + service + "\", \"" + action + "\"," + JSON.stringify(actionArgs) + ");"
);
return;
} catch (e) {}
}
// If actionArgs is not provided, default to an empty array
actionArgs = actionArgs || [];
// Register the callbacks and add the callbackId to the positional
// arguments if given.
if (successCallback || failCallback) {
callbackId = service + cordova.callbackId++;
cordova.callbacks[callbackId] =
{success:successCallback, fail:failCallback};
}
actionArgs = massageArgsJsToNative(actionArgs);
var command = [callbackId, service, action, actionArgs];
// Stringify and queue the command. We stringify to command now to
// effectively clone the command arguments in case they are mutated before
// the command is executed.
commandQueue.push(JSON.stringify(command));
if (bridgeMode === jsToNativeModes.WK_WEBVIEW_BINDING) {
window.webkit.messageHandlers.cordova.postMessage(command);
} else {
// If we're in the context of a stringByEvaluatingJavaScriptFromString call,
// then the queue will be flushed when it returns; no need for a poke.
// Also, if there is already a command in the queue, then we've already
// poked the native side, so there is no reason to do so again.
if (!isInContextOfEvalJs && commandQueue.length == 1) {
pokeNative();
}
}
}
function pokeNative() {
switch (bridgeMode) {
case jsToNativeModes.XHR_NO_PAYLOAD:
case jsToNativeModes.XHR_WITH_PAYLOAD:
case jsToNativeModes.XHR_OPTIONAL_PAYLOAD:
pokeNativeViaXhr();
break;
default: // iframe-based.
pokeNativeViaIframe();
}
}
function pokeNativeViaXhr() {
// This prevents sending an XHR when there is already one being sent.
// This should happen only in rare circumstances (refer to unit tests).
if (execXhr && execXhr.readyState != 4) {
execXhr = null;
}
// Re-using the XHR improves exec() performance by about 10%.
execXhr = execXhr || new XMLHttpRequest();
// Changing this to a GET will make the XHR reach the URIProtocol on 4.2.
// For some reason it still doesn't work though...
// Add a timestamp to the query param to prevent caching.
execXhr.open('HEAD', "/!gap_exec?" + (+new Date()), true);
if (!vcHeaderValue) {
vcHeaderValue = /.*\((.*)\)$/.exec(navigator.userAgent)[1];
}
execXhr.setRequestHeader('vc', vcHeaderValue);
execXhr.setRequestHeader('rc', ++requestCount);
if (shouldBundleCommandJson()) {
execXhr.setRequestHeader('cmds', iOSExec.nativeFetchMessages());
}
execXhr.send(null);
}
function pokeNativeViaIframe() {
// CB-5488 - Don't attempt to create iframe before document.body is available.
if (!document.body) {
setTimeout(pokeNativeViaIframe);
return;
}
if (bridgeMode === jsToNativeModes.IFRAME_HASH_NO_PAYLOAD || bridgeMode === jsToNativeModes.IFRAME_HASH_WITH_PAYLOAD) {
// TODO: This bridge mode doesn't properly support being removed from the DOM (CB-7735)
if (!execHashIframe) {
execHashIframe = document.createElement('iframe');
execHashIframe.style.display = 'none';
document.body.appendChild(execHashIframe);
// Hash changes don't work on about:blank, so switch it to file:///.
execHashIframe.contentWindow.history.replaceState(null, null, 'file:///#');
}
// The delegate method is called only when the hash changes, so toggle it back and forth.
hashToggle = hashToggle ^ 3;
var hashValue = '%0' + hashToggle;
if (bridgeMode === jsToNativeModes.IFRAME_HASH_WITH_PAYLOAD) {
hashValue += iOSExec.nativeFetchMessages();
}
execHashIframe.contentWindow.location.hash = hashValue;
} else {
// Check if they've removed it from the DOM, and put it back if so.
if (execIframe && execIframe.contentWindow) {
execIframe.contentWindow.location = 'gap://ready';
} else {
execIframe = document.createElement('iframe');
execIframe.style.display = 'none';
execIframe.src = 'gap://ready';
document.body.appendChild(execIframe);
}
// Use a timer to protect against iframe being unloaded during the poke (CB-7735).
// This makes the bridge ~ 7% slower, but works around the poke getting lost
// when the iframe is removed from the DOM.
// An onunload listener could be used in the case where the iframe has just been
// created, but since unload events fire only once, it doesn't work in the normal
// case of iframe reuse (where unload will have already fired due to the attempted
// navigation of the page).
failSafeTimerId = setTimeout(function() {
if (commandQueue.length) {
pokeNative();
}
}, 50); // Making this > 0 improves performance (marginally) in the normal case (where it doesn't fire).
}
}
iOSExec.jsToNativeModes = jsToNativeModes;
iOSExec.setJsToNativeBridgeMode = function(mode) {
// Remove the iFrame since it may be no longer required, and its existence
// can trigger browser bugs.
// https://issues.apache.org/jira/browse/CB-593
if (execIframe) {
if (execIframe.parentNode) {
execIframe.parentNode.removeChild(execIframe);
}
execIframe = null;
}
bridgeMode = mode;
};
iOSExec.nativeFetchMessages = function() {
// Stop listing for window detatch once native side confirms poke.
if (failSafeTimerId) {
clearTimeout(failSafeTimerId);
failSafeTimerId = 0;
}
// Each entry in commandQueue is a JSON string already.
if (!commandQueue.length) {
return '';
}
var json = '[' + commandQueue.join(',') + ']';
commandQueue.length = 0;
return json;
};
iOSExec.nativeCallback = function(callbackId, status, message, keepCallback) {
return iOSExec.nativeEvalAndFetch(function() {
var success = status === 0 || status === 1;
var args = convertMessageToArgsNativeToJs(message);
cordova.callbackFromNative(callbackId, success, status, args, keepCallback);
});
};
iOSExec.nativeEvalAndFetch = function(func) {
// This shouldn't be nested, but better to be safe.
isInContextOfEvalJs++;
try {
func();
return iOSExec.nativeFetchMessages();
} finally {
isInContextOfEvalJs--;
}
};
module.exports = iOSExec;
/*
*
* 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.
*
*/
module.exports = {
id: 'ios',
bootstrap: function() {
require('cordova/channel').onNativeReady.fire();
}
};
// 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;
}
});
......
/*
*
* 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.
*
*/
/**
* Creates a gap bridge iframe used to notify the native code about queued
* commands.
*/
var cordova = require('cordova'),
channel = require('cordova/channel'),
utils = require('cordova/utils'),
base64 = require('cordova/base64'),
// XHR mode does not work on iOS 4.2.
// XHR mode's main advantage is working around a bug in -webkit-scroll, which
// doesn't exist only on iOS 5.x devices.
// IFRAME_NAV is the fastest.
// IFRAME_HASH could be made to enable synchronous bridge calls if we wanted this feature.
jsToNativeModes = {
IFRAME_NAV: 0, // Default. Uses a new iframe for each poke.
// XHR bridge appears to be flaky sometimes: CB-3900, CB-3359, CB-5457, CB-4970, CB-4998, CB-5134
XHR_NO_PAYLOAD: 1, // About the same speed as IFRAME_NAV. Performance not about the same as IFRAME_NAV, but more variable.
XHR_WITH_PAYLOAD: 2, // Flakey, and not as performant
XHR_OPTIONAL_PAYLOAD: 3, // Flakey, and not as performant
IFRAME_HASH_NO_PAYLOAD: 4, // Not fully baked. A bit faster than IFRAME_NAV, but risks jank since poke happens synchronously.
IFRAME_HASH_WITH_PAYLOAD: 5, // Slower than no payload. Maybe since it has to be URI encoded / decoded.
WK_WEBVIEW_BINDING: 6 // Only way that works for WKWebView :)
},
bridgeMode,
execIframe,
execHashIframe,
hashToggle = 1,
execXhr,
requestCount = 0,
vcHeaderValue = null,
commandQueue = [], // Contains pending JS->Native messages.
isInContextOfEvalJs = 0,
failSafeTimerId = 0;
function shouldBundleCommandJson() {
if (bridgeMode === jsToNativeModes.XHR_WITH_PAYLOAD) {
return true;
}
if (bridgeMode === jsToNativeModes.XHR_OPTIONAL_PAYLOAD) {
var payloadLength = 0;
for (var i = 0; i < commandQueue.length; ++i) {
payloadLength += commandQueue[i].length;
}
// The value here was determined using the benchmark within CordovaLibApp on an iPad 3.
return payloadLength < 4500;
}
return false;
}
function massageArgsJsToNative(args) {
if (!args || utils.typeName(args) != 'Array') {
return args;
}
var ret = [];
args.forEach(function(arg, i) {
if (utils.typeName(arg) == 'ArrayBuffer') {
ret.push({
'CDVType': 'ArrayBuffer',
'data': base64.fromArrayBuffer(arg)
});
} else {
ret.push(arg);
}
});
return ret;
}
function massageMessageNativeToJs(message) {
if (message.CDVType == 'ArrayBuffer') {
var stringToArrayBuffer = function(str) {
var ret = new Uint8Array(str.length);
for (var i = 0; i < str.length; i++) {
ret[i] = str.charCodeAt(i);
}
return ret.buffer;
};
var base64ToArrayBuffer = function(b64) {
return stringToArrayBuffer(atob(b64));
};
message = base64ToArrayBuffer(message.data);
}
return message;
}
function convertMessageToArgsNativeToJs(message) {
var args = [];
if (!message || !message.hasOwnProperty('CDVType')) {
args.push(message);
} else if (message.CDVType == 'MultiPart') {
message.messages.forEach(function(e) {
args.push(massageMessageNativeToJs(e));
});
} else {
args.push(massageMessageNativeToJs(message));
}
return args;
}
function iOSExec() {
if (bridgeMode === undefined) {
bridgeMode = jsToNativeModes.IFRAME_NAV;
}
if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.cordova && window.webkit.messageHandlers.cordova.postMessage) {
bridgeMode = jsToNativeModes.WK_WEBVIEW_BINDING;
}
var successCallback, failCallback, service, action, actionArgs, splitCommand;
var callbackId = null;
if (typeof arguments[0] !== "string") {
// FORMAT ONE
successCallback = arguments[0];
failCallback = arguments[1];
service = arguments[2];
action = arguments[3];
actionArgs = arguments[4];
// Since we need to maintain backwards compatibility, we have to pass
// an invalid callbackId even if no callback was provided since plugins
// will be expecting it. The Cordova.exec() implementation allocates
// an invalid callbackId and passes it even if no callbacks were given.
callbackId = 'INVALID';
} else {
// FORMAT TWO, REMOVED
try {
splitCommand = arguments[0].split(".");
action = splitCommand.pop();
service = splitCommand.join(".");
actionArgs = Array.prototype.splice.call(arguments, 1);
console.log('The old format of this exec call has been removed (deprecated since 2.1). Change to: ' +
"cordova.exec(null, null, \"" + service + "\", \"" + action + "\"," + JSON.stringify(actionArgs) + ");"
);
return;
} catch (e) {}
}
// If actionArgs is not provided, default to an empty array
actionArgs = actionArgs || [];
// Register the callbacks and add the callbackId to the positional
// arguments if given.
if (successCallback || failCallback) {
callbackId = service + cordova.callbackId++;
cordova.callbacks[callbackId] =
{success:successCallback, fail:failCallback};
}
actionArgs = massageArgsJsToNative(actionArgs);
var command = [callbackId, service, action, actionArgs];
// Stringify and queue the command. We stringify to command now to
// effectively clone the command arguments in case they are mutated before
// the command is executed.
commandQueue.push(JSON.stringify(command));
if (bridgeMode === jsToNativeModes.WK_WEBVIEW_BINDING) {
window.webkit.messageHandlers.cordova.postMessage(command);
} else {
// If we're in the context of a stringByEvaluatingJavaScriptFromString call,
// then the queue will be flushed when it returns; no need for a poke.
// Also, if there is already a command in the queue, then we've already
// poked the native side, so there is no reason to do so again.
if (!isInContextOfEvalJs && commandQueue.length == 1) {
pokeNative();
}
}
}
function pokeNative() {
switch (bridgeMode) {
case jsToNativeModes.XHR_NO_PAYLOAD:
case jsToNativeModes.XHR_WITH_PAYLOAD:
case jsToNativeModes.XHR_OPTIONAL_PAYLOAD:
pokeNativeViaXhr();
break;
default: // iframe-based.
pokeNativeViaIframe();
}
}
function pokeNativeViaXhr() {
// This prevents sending an XHR when there is already one being sent.
// This should happen only in rare circumstances (refer to unit tests).
if (execXhr && execXhr.readyState != 4) {
execXhr = null;
}
// Re-using the XHR improves exec() performance by about 10%.
execXhr = execXhr || new XMLHttpRequest();
// Changing this to a GET will make the XHR reach the URIProtocol on 4.2.
// For some reason it still doesn't work though...
// Add a timestamp to the query param to prevent caching.
execXhr.open('HEAD', "/!gap_exec?" + (+new Date()), true);
if (!vcHeaderValue) {
vcHeaderValue = /.*\((.*)\)$/.exec(navigator.userAgent)[1];
}
execXhr.setRequestHeader('vc', vcHeaderValue);
execXhr.setRequestHeader('rc', ++requestCount);
if (shouldBundleCommandJson()) {
execXhr.setRequestHeader('cmds', iOSExec.nativeFetchMessages());
}
execXhr.send(null);
}
function pokeNativeViaIframe() {
// CB-5488 - Don't attempt to create iframe before document.body is available.
if (!document.body) {
setTimeout(pokeNativeViaIframe);
return;
}
if (bridgeMode === jsToNativeModes.IFRAME_HASH_NO_PAYLOAD || bridgeMode === jsToNativeModes.IFRAME_HASH_WITH_PAYLOAD) {
// TODO: This bridge mode doesn't properly support being removed from the DOM (CB-7735)
if (!execHashIframe) {
execHashIframe = document.createElement('iframe');
execHashIframe.style.display = 'none';
document.body.appendChild(execHashIframe);
// Hash changes don't work on about:blank, so switch it to file:///.
execHashIframe.contentWindow.history.replaceState(null, null, 'file:///#');
}
// The delegate method is called only when the hash changes, so toggle it back and forth.
hashToggle = hashToggle ^ 3;
var hashValue = '%0' + hashToggle;
if (bridgeMode === jsToNativeModes.IFRAME_HASH_WITH_PAYLOAD) {
hashValue += iOSExec.nativeFetchMessages();
}
execHashIframe.contentWindow.location.hash = hashValue;
} else {
// Check if they've removed it from the DOM, and put it back if so.
if (execIframe && execIframe.contentWindow) {
execIframe.contentWindow.location = 'gap://ready';
} else {
execIframe = document.createElement('iframe');
execIframe.style.display = 'none';
execIframe.src = 'gap://ready';
document.body.appendChild(execIframe);
}
// Use a timer to protect against iframe being unloaded during the poke (CB-7735).
// This makes the bridge ~ 7% slower, but works around the poke getting lost
// when the iframe is removed from the DOM.
// An onunload listener could be used in the case where the iframe has just been
// created, but since unload events fire only once, it doesn't work in the normal
// case of iframe reuse (where unload will have already fired due to the attempted
// navigation of the page).
failSafeTimerId = setTimeout(function() {
if (commandQueue.length) {
pokeNative();
}
}, 50); // Making this > 0 improves performance (marginally) in the normal case (where it doesn't fire).
}
}
iOSExec.jsToNativeModes = jsToNativeModes;
iOSExec.setJsToNativeBridgeMode = function(mode) {
// Remove the iFrame since it may be no longer required, and its existence
// can trigger browser bugs.
// https://issues.apache.org/jira/browse/CB-593
if (execIframe) {
if (execIframe.parentNode) {
execIframe.parentNode.removeChild(execIframe);
}
execIframe = null;
}
bridgeMode = mode;
};
iOSExec.nativeFetchMessages = function() {
// Stop listing for window detatch once native side confirms poke.
if (failSafeTimerId) {
clearTimeout(failSafeTimerId);
failSafeTimerId = 0;
}
// Each entry in commandQueue is a JSON string already.
if (!commandQueue.length) {
return '';
}
var json = '[' + commandQueue.join(',') + ']';
commandQueue.length = 0;
return json;
};
iOSExec.nativeCallback = function(callbackId, status, message, keepCallback) {
return iOSExec.nativeEvalAndFetch(function() {
var success = status === 0 || status === 1;
var args = convertMessageToArgsNativeToJs(message);
cordova.callbackFromNative(callbackId, success, status, args, keepCallback);
});
};
iOSExec.nativeEvalAndFetch = function(func) {
// This shouldn't be nested, but better to be safe.
isInContextOfEvalJs++;
try {
func();
return iOSExec.nativeFetchMessages();
} finally {
isInContextOfEvalJs--;
}
};
module.exports = iOSExec;
/*
*
* 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.
*
*/
module.exports = {
id: 'ios',
bootstrap: function() {
require('cordova/channel').onNativeReady.fire();
}
};
// 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;
}
});
......
......@@ -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"
]
......@@ -47,9 +47,10 @@ module.exports.metadata =
// TOP OF 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
......
{
"ios": "3.9.1"
}
\ No newline at end of file
......@@ -57,15 +57,15 @@ 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"
]
},
{
"file": "plugins/org.apache.cordova.device/src/windows/DeviceProxy.js",
"id": "org.apache.cordova.device.DeviceProxy",
"file": "plugins/cordova-plugin-device/src/windows/DeviceProxy.js",
"id": "cordova-plugin-device.DeviceProxy",
"merges": [
""
]
......@@ -77,8 +77,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.DeviceProxy", function(require, exports, module) { /*
cordova.define("cordova-plugin-device.DeviceProxy", function(require, exports, module) { /*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE 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
......
......@@ -189,7 +189,7 @@ exports.buildToastTemplate = function (options) {
// template with Image
if (imageNode !== '') {
templateName = "ToastImageAndText";
};
}
} else {
imageNode = "";
}
......@@ -294,7 +294,7 @@ exports.isToastScheduled = function (toast) {
*/
exports.isToastTriggered = function (toast) {
var id = this.getToastId(toast),
notification = this.getAll(id)[0];
notification = this.getAll([id])[0],
fireDate = new Date((notification.at) * 1000);
if (this.isRepeating(notification))
......@@ -390,7 +390,7 @@ exports.fireEvent = function (event, notification) {
args = [event, state];
}
if (this.isReady) {
if (this.isReady && plugin) {
plugin.fireEvent.apply(plugin, args);
} else {
this.eventQueue.push(args);
......
......@@ -84,7 +84,7 @@
}
},
"dependent_plugins": {
"org.apache.cordova.device": {
"cordova-plugin-device": {
"PACKAGE_NAME": "de.appplant.localnotification.example"
}
}
......
<!---
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.
<!--
# license: 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.
-->
# org.apache.cordova.device
# cordova-plugin-device
[![Build Status](https://travis-ci.org/apache/cordova-plugin-device.svg?branch=master)](https://travis-ci.org/apache/cordova-plugin-device)
This plugin defines a global `device` object, which describes the device's hardware and software.
Although the object is in the global scope, it is not available until after the `deviceready` event.
......@@ -29,7 +31,7 @@ Although the object is in the global scope, it is not available until after the
## Installation
cordova plugin add org.apache.cordova.device
cordova plugin add cordova-plugin-device
## Properties
......
......@@ -96,3 +96,19 @@
* Support for Windows Phone 8 ANID2 ANID is only supported up to Windows Phone 7.5
* CB-8351 Use a local copy of uniqueAppInstanceIdentifier rather than CordovaLib's version
* browser: Fixed a bug that caused an "cannot call method of undefined" error if the browser's user agent wasn't recognized
### 1.0.0 (Apr 15, 2015)
* CB-8746 gave plugin major version bump
* CB-8683 changed plugin-id to pacakge-name
* CB-8653 properly updated translated docs to use new id
* CB-8653 updated translated docs to use new id
* Use TRAVIS_BUILD_DIR, install paramedic by npm
* CB-8653 Updated Readme
* remove defunct windows8 version
* add travis badge
* Add cross-plugin ios paramedic test running for TravisCI
* CB-8538 Added package.json file
### 1.0.1 (Jun 17, 2015)
* CB-9128 cordova-plugin-device documentation translation: cordova-plugin-device
* Attempts to corrent npm markdown issue
{
"name": "cordova-plugin-device",
"version": "1.0.1",
"description": "Cordova Device Plugin",
"cordova": {
"id": "cordova-plugin-device",
"platforms": [
"firefoxos",
"tizen",
"android",
"amazon-fireos",
"ubuntu",
"ios",
"blackberry10",
"wp7",
"wp8",
"windows8",
"windows",
"browser"
]
},
"repository": {
"type": "git",
"url": "https://github.com/apache/cordova-plugin-device"
},
"keywords": [
"cordova",
"device",
"ecosystem:cordova",
"cordova-firefoxos",
"cordova-tizen",
"cordova-android",
"cordova-amazon-fireos",
"cordova-ubuntu",
"cordova-ios",
"cordova-blackberry10",
"cordova-wp7",
"cordova-wp8",
"cordova-windows8",
"cordova-windows",
"cordova-browser"
],
"author": "Apache Software Foundation",
"license": "Apache 2.0"
}
......@@ -21,8 +21,8 @@
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
xmlns:rim="http://www.blackberry.com/ns/widgets"
xmlns:android="http://schemas.android.com/apk/res/android"
id="org.apache.cordova.device"
version="0.3.0">
id="cordova-plugin-device"
version="1.0.1">
<name>Device</name>
<description>Cordova Device Plugin</description>
<license>Apache 2.0</license>
......@@ -138,13 +138,6 @@
<source-file src="src/wp/Device.cs" />
</platform>
<!-- windows8 -->
<platform name="windows8">
<js-module src="src/windows8/DeviceProxy.js" name="DeviceProxy">
<merges target="" />
</js-module>
</platform>
<!-- windows -->
<platform name="windows">
<js-module src="src/windows/DeviceProxy.js" name="DeviceProxy">
......
......@@ -21,8 +21,8 @@
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
xmlns:rim="http://www.blackberry.com/ns/widgets"
xmlns:android="http://schemas.android.com/apk/res/android"
id="org.apache.cordova.device.tests"
version="0.2.14">
id="cordova-plugin-device-tests"
version="1.0.1">
<name>Cordova Device Plugin Tests</name>
<license>Apache 2.0</license>
......
[![PayPayl donate button](https://img.shields.io/badge/paypal-donate-yellow.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=L3HKQCD9UA35A "Donate once-off to this project using Paypal")
#### :bangbang: Please vote for that cordova-windows issue :bangbang:
https://issues.apache.org/jira/browse/CB-8674
#### :bangbang: Please vote for these cordova-windows issues :bangbang:
1. https://issues.apache.org/jira/browse/CB-8674 _(Missing launch arguments)_
2. https://issues.apache.org/jira/browse/CB-8946 _(Missing ToastCapable flag)_
Thanks a lot!
......
......@@ -3,7 +3,7 @@
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
xmlns:android="http://schemas.android.com/apk/res/android"
id="de.appplant.cordova.plugin.local-notification"
version="0.8.2dev">
version="0.8.2-dev">
<name>LocalNotification</name>
......@@ -19,11 +19,12 @@
<!-- cordova -->
<engines>
<engine name="cordova" version=">=3.0.0" />
<engine name="cordova" version=">=3.6.0" />
<engine name="cordova" version="<4.0.0" />
</engines>
<!-- dependencies -->
<dependency id="org.apache.cordova.device" />
<dependency id="cordova-plugin-device" />
<!-- info -->
<info>
......@@ -52,6 +53,8 @@
<!-- ios -->
<platform name="ios">
<dependency id="de.appplant.cordova.common.registerusernotificationsettings" />
<config-file target="config.xml" parent="/*">
<feature name="LocalNotification">
<param name="ios-package" value="APPLocalNotification" onload="true" />
......@@ -71,19 +74,13 @@
<header-file src="src/ios/UILocalNotification+APPLocalNotification.h" />
<source-file src="src/ios/UILocalNotification+APPLocalNotification.m" />
<hook
type="after_platform_add"
src="scripts/ios/didRegisterUserNotificationSettings.js" />
<hook
type="after_plugin_install"
src="scripts/ios/didRegisterUserNotificationSettings.js" />
</platform>
<!-- android -->
<platform name="android">
<dependency id="android.support.v4" />
<config-file target="res/xml/config.xml" parent="/*">
<feature name="LocalNotification">
<param name="android-package" value="de.appplant.cordova.plugin.localnotification.LocalNotification"/>
......@@ -133,8 +130,6 @@
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
</config-file>
<lib-file src="libs/android/android-support-v4.jar" />
<source-file
src="src/android/LocalNotification.java"
target-dir="src/de/appplant/cordova/plugin/localnotification" />
......
......@@ -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 ()
......
......@@ -189,7 +189,7 @@ exports.buildToastTemplate = function (options) {
// template with Image
if (imageNode !== '') {
templateName = "ToastImageAndText";
};
}
} else {
imageNode = "";
}
......@@ -294,7 +294,7 @@ exports.isToastScheduled = function (toast) {
*/
exports.isToastTriggered = function (toast) {
var id = this.getToastId(toast),
notification = this.getAll(id)[0];
notification = this.getAll([id])[0],
fireDate = new Date((notification.at) * 1000);
if (this.isRepeating(notification))
......@@ -390,7 +390,7 @@ exports.fireEvent = function (event, notification) {
args = [event, state];
}
if (this.isReady) {
if (this.isReady && plugin) {
plugin.fireEvent.apply(plugin, args);
} else {
this.eventQueue.push(args);
......
......@@ -54,11 +54,18 @@
},
"de.appplant.cordova.plugin.local-notification": {
"source": {
"type": "git",
"url": "https://github.com/katzer/cordova-plugin-local-notifications",
"subdir": "."
"type": "local",
"path": "/Users/sebastian/Documents/github/cordova-plugin-local-notifications"
},
"is_top_level": true,
"variables": {}
},
"cordova-plugin-device": {
"source": {
"type": "registry",
"id": "cordova-plugin-device"
},
"is_top_level": false,
"variables": {}
}
}
\ No newline at end of file
......@@ -32,12 +32,6 @@
}
]
}
},
"*-Info.plist": {
"parents": {
"UIStatusBarHidden": [],
"UIViewControllerBasedStatusBarAppearance": []
}
}
}
},
......@@ -45,6 +39,9 @@
"android.support.v4": {
"PACKAGE_NAME": "de.appplant.localnotification.example"
},
"de.appplant.cordova.common.registerusernotificationsettings": {
"PACKAGE_NAME": "de.appplant.localnotification.example"
},
"nl.x-services.plugins.toast": {
"PACKAGE_NAME": "de.appplant.localnotification.example"
},
......@@ -53,7 +50,7 @@
}
},
"dependent_plugins": {
"org.apache.cordova.device": {
"cordova-plugin-device": {
"PACKAGE_NAME": "de.appplant.localnotification.example"
}
}
......
<!---
license: 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.
-->
# org.apache.cordova.device
Plugin documentation: [doc/index.md](doc/index.md)
<!---
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.
-->
# org.apache.cordova.device
Dieses Plugin definiert eine globale `device` -Objekt, das des Geräts Hard- und Software beschreibt. Das Objekt im globalen Gültigkeitsbereich ist es zwar nicht verfügbar bis nach dem `deviceready` Ereignis.
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
console.log(device.cordova);
}
## Installation
cordova plugin add org.apache.cordova.device
## Eigenschaften
* device.cordova
* device.model
* device.platform
* device.uuid
* device.version
## device.cordova
Rufen Sie die Version von Cordova, die auf dem Gerät ausgeführt.
### Unterstützte Plattformen
* Amazon Fire OS
* Android
* BlackBerry 10
* Browser
* Firefox OS
* iOS
* Tizen
* Windows Phone 7 und 8
* Windows 8
## device.model
Die `device.model` gibt den Namen der Modell- oder des Geräts zurück. Der Wert wird vom Gerätehersteller festgelegt und kann zwischen den Versionen des gleichen Produkts unterschiedlich sein.
### Unterstützte Plattformen
* Android
* BlackBerry 10
* Browser
* iOS
* Tizen
* Windows Phone 7 und 8
* Windows 8
### Kurzes Beispiel
// Android: Nexus One returns "Passion" (Nexus One code name)
// Motorola Droid returns "voles"
// BlackBerry: Torch 9800 returns "9800"
// Browser: Google Chrome returns "Chrome"
// Safari returns "Safari"
// iOS: for the iPad Mini, returns iPad2,5; iPhone 5 is iPhone 5,1. Finden Sie unter http://theiphonewiki.com/wiki/index.php?title=Models / / Var-Modell = device.model;
### Android Eigenarten
* Ruft den [Produktname][1] anstelle des [Modellnamens][2], das ist oft der Codename für die Produktion. Beispielsweise das Nexus One gibt `Passion` , und Motorola Droid gibt`voles`.
[1]: http://developer.android.com/reference/android/os/Build.html#PRODUCT
[2]: http://developer.android.com/reference/android/os/Build.html#MODEL
### Tizen Macken
* Gibt z. B. das Gerätemodell von dem Kreditor zugeordnet,`TIZEN`
### Windows Phone 7 und 8 Eigenarten
* Gibt das vom Hersteller angegebenen Gerätemodell zurück. Beispielsweise gibt der Samsung-Fokus`SGH-i917`.
## device.platform
Name des Betriebssystems des Geräts zu erhalten.
var string = device.platform;
### Unterstützte Plattformen
* Android
* BlackBerry 10
* Browser4
* Firefox OS
* iOS
* Tizen
* Windows Phone 7 und 8
* Windows 8
### Kurzes Beispiel
// Depending on the device, a few examples are:
// - "Android"
// - "BlackBerry 10"
// - Browser: returns "MacIntel" on Mac
// returns "Win32" on Windows
// - "iOS"
// - "WinCE"
// - "Tizen"
var devicePlatform = device.platform;
### Windows Phone 7 Macken
Windows Phone 7 Geräte melden die Plattform als`WinCE`.
### Windows Phone 8 Macken
Windows Phone 8 Geräte melden die Plattform als`Win32NT`.
## device.uuid
Des Geräts Universally Unique Identifier ([UUID][3] zu erhalten).
[3]: http://en.wikipedia.org/wiki/Universally_Unique_Identifier
var string = device.uuid;
### Beschreibung
Die Details wie eine UUID generiert wird werden vom Gerätehersteller und beziehen sich auf die Plattform oder das Modell des Geräts.
### Unterstützte Plattformen
* Android
* BlackBerry 10
* iOS
* Tizen
* Windows Phone 7 und 8
* Windows 8
### Kurzes Beispiel
/ / Android: wird eine zufällige 64-Bit-Ganzzahl (als Zeichenfolge, wieder!) / / die ganze Zahl wird beim ersten Start des Geräts erzeugt / / / / BlackBerry: gibt die PIN-Nummer des Gerätes / / Dies ist eine neunstellige eindeutige Ganzzahl (als String, obwohl!) / / / / iPhone: (paraphrasiert aus der Dokumentation zur UIDevice-Klasse) / / liefert eine Reihe von Hash-Werte, die aus mehreren Hardware erstellt identifiziert.
/ / Es ist gewährleistet, dass für jedes Gerät eindeutig sein und kann nicht gebunden werden / / an den Benutzer weitergeleitet.
/ / Windows Phone 7: gibt einen Hash des Gerät + aktueller Benutzer, / / wenn der Benutzer nicht definiert ist, eine Guid generiert und wird weiter bestehen, bis die app deinstalliert wird / / Tizen: gibt das Gerät IMEI (International Mobile Equipment Identity oder IMEI ist eine Zahl / / einzigartig für jedes GSM- und UMTS-Handy.
var deviceID = device.uuid;
### iOS Quirk
Die `uuid` auf iOS ist nicht eindeutig zu einem Gerät, aber für jede Anwendung, für jede Installation variiert. Es ändert sich, wenn Sie löschen und neu die app installieren, und möglicherweise auch beim iOS zu aktualisieren, oder auch ein Upgrade möglich die app pro Version (scheinbaren in iOS 5.1). Die `uuid` ist kein zuverlässiger Wert.
### Windows Phone 7 und 8 Eigenarten
Die `uuid` für Windows Phone 7 die Berechtigung erfordert `ID_CAP_IDENTITY_DEVICE` . Microsoft wird diese Eigenschaft wahrscheinlich bald abzuschaffen. Wenn die Funktion nicht verfügbar ist, generiert die Anwendung eine persistente Guid, die für die Dauer der Installation der Anwendung auf dem Gerät gewährleistet ist.
## device.version
Version des Betriebssystems zu erhalten.
var string = device.version;
### Unterstützte Plattformen
* Android 2.1 +
* BlackBerry 10
* Browser
* iOS
* Tizen
* Windows Phone 7 und 8
* Windows 8
### Kurzes Beispiel
// Android: Froyo OS would return "2.2"
// Eclair OS would return "2.1", "2.0.1", or "2.0"
// Version can also return update level "2.1-update1"
//
// BlackBerry: Torch 9800 using OS 6.0 would return "6.0.0.600"
//
// Browser: Returns version number for the browser
//
// iPhone: iOS 3.2 returns "3.2"
//
// Windows Phone 7: returns current OS version number, ex. on Mango returns 7.10.7720
// Tizen: returns "TIZEN_20120425_2"
var deviceVersion = device.version;
\ No newline at end of file
<!---
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.
-->
# org.apache.cordova.device
Este plugin define un global `device` objeto que describe del dispositivo hardware y software. Aunque el objeto está en el ámbito global, no está disponible hasta después de la `deviceready` evento.
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
console.log(device.cordova);
}
## Instalación
cordova plugin add org.apache.cordova.device
## Propiedades
* device.cordova
* device.model
* device.platform
* device.uuid
* device.version
## device.cordova
Obtener la versión de Cordova que se ejecuta en el dispositivo.
### Plataformas soportadas
* Amazon fire OS
* Android
* BlackBerry 10
* Explorador
* Firefox OS
* iOS
* Tizen
* Windows Phone 7 y 8
* Windows 8
## device.model
El `device.model` devuelve el nombre de modelo del dispositivo o producto. El valor es fijado por el fabricante del dispositivo y puede ser diferente a través de versiones del mismo producto.
### Plataformas soportadas
* Android
* BlackBerry 10
* Explorador
* iOS
* Tizen
* Windows Phone 7 y 8
* Windows 8
### Ejemplo rápido
// Android: Nexus One returns "Passion" (Nexus One code name)
// Motorola Droid returns "voles"
// BlackBerry: Torch 9800 returns "9800"
// Browser: Google Chrome returns "Chrome"
// Safari returns "Safari"
// iOS: for the iPad Mini, returns iPad2,5; iPhone 5 is iPhone 5,1. See http://theiphonewiki.com/wiki/index.php?title=Models
//
var model = device.model;
### Rarezas Android
* Obtiene el [nombre del producto][1] en lugar del [nombre de la modelo][2], que es a menudo el nombre de código de producción. Por ejemplo, el Nexus One devuelve `Passion` y Motorola Droid devuelve `voles`.
[1]: http://developer.android.com/reference/android/os/Build.html#PRODUCT
[2]: http://developer.android.com/reference/android/os/Build.html#MODEL
### Rarezas Tizen
* Devuelve que el modelo de dispositivo asignado por el proveedor, por ejemplo, `TIZEN`
### Windows Phone 7 y 8 rarezas
* Devuelve el modelo de dispositivo especificado por el fabricante. Por ejemplo, el Samsung Focus devuelve `SGH-i917`.
## device.platform
Obtener el nombre del sistema operativo del dispositivo.
var string = device.platform;
### Plataformas soportadas
* Android
* BlackBerry 10
* Browser4
* Firefox OS
* iOS
* Tizen
* Windows Phone 7 y 8
* Windows 8
### Ejemplo rápido
// Depending on the device, a few examples are:
// - "Android"
// - "BlackBerry 10"
// - Browser: returns "MacIntel" on Mac
// returns "Win32" on Windows
// - "iOS"
// - "WinCE"
// - "Tizen"
var devicePlatform = device.platform;
### Windows Phone 7 rarezas
Dispositivos Windows Phone 7 informe de la plataforma como `WinCE`.
### Windows Phone 8 rarezas
Dispositivos Windows Phone 8 Informe la plataforma como `Win32NT`.
## device.uuid
Obtener identificador universalmente única del dispositivo ([UUID][3]).
[3]: http://en.wikipedia.org/wiki/Universally_Unique_Identifier
var string = device.uuid;
### Descripción
Los detalles de cómo se genera un UUID son determinados por el fabricante del dispositivo y son específicos a la plataforma del dispositivo o modelo.
### Plataformas soportadas
* Android
* BlackBerry 10
* iOS
* Tizen
* Windows Phone 7 y 8
* Windows 8
### Ejemplo rápido
// Android: devuelve un entero de 64 bits al azar (como una cadena, otra vez!)
// el entero es generado en el primer arranque del dispositivo
//
// BlackBerry: devuelve el número PIN del dispositivo
// este es un entero único de nueve dígitos (como una cadena, aunque!)
//
// iPhone: (parafraseado de la documentación de la clase UIDevice)
// devuelve una cadena de valores hash creado a partir
// de múltiples hardware identifica.
/ / Está garantizado para ser único para cada dispositivo y no puede ser atado / / a la cuenta de usuario.
// Windows Phone 7: devuelve un hash de dispositivo + usuario actual,
// si el usuario no está definido, un guid generado y persistirá hasta que se desinstala la aplicación
//
// Tizen: devuelve el dispositivo IMEI (identidad de equipo móvil internacional o IMEI es un número
// único para cada teléfono móvil GSM y UMTS.
var deviceID = device.uuid;
### iOS chanfle
El `uuid` en iOS no es exclusiva de un dispositivo, pero varía para cada aplicación, para cada instalación. Cambia si puedes borrar y volver a instalar la aplicación, y posiblemente también cuándo actualizar iOS, o incluso mejorar la aplicación por la versión (evidente en iOS 5.1). El `uuid` no es un valor confiable.
### Windows Phone 7 y 8 rarezas
El `uuid` para Windows Phone 7 requiere el permiso `ID_CAP_IDENTITY_DEVICE`. Microsoft pronto probablemente desaprueban esta propiedad. Si la capacidad no está disponible, la aplicación genera un guid persistente que se mantiene durante la duración de la instalación de la aplicación en el dispositivo.
## device.version
Obtener la versión del sistema operativo.
var string = device.version;
### Plataformas soportadas
* Android 2.1 +
* BlackBerry 10
* Explorador
* iOS
* Tizen
* Windows Phone 7 y 8
* Windows 8
### Ejemplo rápido
// Android: Froyo OS would return "2.2"
// Eclair OS would return "2.1", "2.0.1", or "2.0"
// Version can also return update level "2.1-update1"
//
// BlackBerry: Torch 9800 using OS 6.0 would return "6.0.0.600"
//
// Browser: Returns version number for the browser
//
// iPhone: iOS 3.2 returns "3.2"
//
// Windows Phone 7: returns current OS version number, ex. el Mango se vuelve 7.10.7720
// Tizen: devuelve "TIZEN_20120425_2"
var deviceVersion = device.version;
\ No newline at end of file
<!---
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.
-->
# org.apache.cordova.device
Ce plugin définit un global `device` objet qui décrit le matériel et les logiciels de l'appareil. Bien que l'objet est dans la portée globale, il n'est pas disponible jusqu'après la `deviceready` événement.
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
console.log(device.cordova);
}
## Installation
cordova plugin add org.apache.cordova.device
## Propriétés
* device.cordova
* device.model
* device.platform
* device.uuid
* device.version
## device.cordova
Retourne la version de Cordova en cours d'exécution sur l'appareil.
### Plates-formes prises en charge
* Amazon Fire OS
* Android
* BlackBerry 10
* Navigateur
* Firefox OS
* iOS
* Paciarelli
* Windows Phone 7 et 8
* Windows 8
## device.model
L'objet `device.model` retourne le nom du modèle de l'appareil/produit. Cette valeur est définie par le fabricant du périphérique et peut varier entre les différentes versions d'un même produit.
### Plates-formes prises en charge
* Android
* BlackBerry 10
* Navigateur
* iOS
* Paciarelli
* Windows Phone 7 et 8
* Windows 8
### Petit exemple
// Android: Nexus One returns "Passion" (Nexus One code name)
// Motorola Droid returns "voles"
// BlackBerry: Torch 9800 returns "9800"
// Browser: Google Chrome returns "Chrome"
// Safari returns "Safari"
// iOS: for the iPad Mini, returns iPad2,5; iPhone 5 is iPhone 5,1. Voir http://theiphonewiki.com/wiki/index.php?title=Models
//
var model = device.model;
### Quirks Android
* Retourne le [nom du produit][1] au lieu du [nom du modèle][2], ce qui équivaut souvent au nom de code de production. Par exemple, `Passion` pour le Nexus One et `voles` pour le Motorola Droid.
[1]: http://developer.android.com/reference/android/os/Build.html#PRODUCT
[2]: http://developer.android.com/reference/android/os/Build.html#MODEL
### Bizarreries de paciarelli
* Retourne le modèle du dispositif, assigné par le vendeur, par exemple `TIZEN`
### Windows Phone 7 et 8 Quirks
* Retourne le modèle de l'appareil spécifié par le fabricant. Par exemple `SGH-i917` pour le Samsung Focus.
## device.platform
Obtenir le nom de système d'exploitation de l'appareil.
var string = device.platform;
### Plates-formes prises en charge
* Android
* BlackBerry 10
* Browser4
* Firefox OS
* iOS
* Paciarelli
* Windows Phone 7 et 8
* Windows 8
### Petit exemple
// Depending on the device, a few examples are:
// - "Android"
// - "BlackBerry 10"
// - Browser: returns "MacIntel" on Mac
// returns "Win32" on Windows
// - "iOS"
// - "WinCE"
// - "Tizen"
var devicePlatform = device.platform;
### Windows Phone 7 Quirks
Appareils Windows Phone 7 rapport de la plate-forme comme`WinCE`.
### Notes au sujet de Windows Phone 8
Appareils Windows Phone 8 rapport de la plate-forme comme`Win32NT`.
## device.uuid
Obtenir Universally Unique Identifier de l'appareil ([UUID][3]).
[3]: http://en.wikipedia.org/wiki/Universally_Unique_Identifier
var string = device.uuid;
### Description
Les détails de comment un UUID généré sont déterminées par le fabricant du périphérique et sont spécifiques à la plate-forme ou le modèle de l'appareil.
### Plates-formes prises en charge
* Android
* BlackBerry 10
* iOS
* Paciarelli
* Windows Phone 7 et 8
* Windows 8
### Petit exemple
// Android : retourne un nombre entier 64-bit aléatoire (sous la forme d'une chaîne de caractères, encore !)
// Ce nombre entier est généré lors du premier démarrage de l'appareil
//
// BlackBerry : retourne le numéro PIN de l'appareil
// Il s'agit d'un nombre entier unique à neuf chiffres (sous la forme d'une chaîne de caractères cependant !)
//
// iPhone : (copié depuis la documentation de la classe UIDevice)
// Retourne une chaîne de caractères générée à partir de plusieurs caractéristiques matérielles.
/ / Il est garanti pour être unique pour chaque appareil et ne peut pas être lié / / pour le compte d'utilisateur.
// Windows Phone 7 : retourne un hashage généré à partir de appareil+utilisateur actuel,
// si aucun utilisateur n'est défini, un guid est généré persistera jusqu'à ce que l'application soit désinstallée
// Tizen : retourne le numéro IMEI (International Mobile Equipment Identity) de l'appareil, ce numéro est
// unique pour chaque téléphone GSM et UMTS.
var deviceID = device.uuid;
### Spécificités iOS
Le `uuid` sur iOS n'est pas propre à un périphérique, mais varie pour chaque application, pour chaque installation. Elle change si vous supprimez, puis réinstallez l'application, et éventuellement aussi quand vous mettre à jour d'iOS, ou même mettre à jour le soft par version (apparent dans iOS 5.1). Le `uuid` n'est pas une valeur fiable.
### Windows Phone 7 et 8 Quirks
Le `uuid` pour Windows Phone 7 requiert l'autorisation `ID_CAP_IDENTITY_DEVICE` . Microsoft va probablement bientôt obsolète de cette propriété. Si la capacité n'est pas disponible, l'application génère un guid persistant qui est maintenu pendant toute la durée de l'installation de l'application sur le périphérique.
## device.version
Téléchargez la version de système d'exploitation.
var string = device.version;
### Plates-formes prises en charge
* Android 2.1+
* BlackBerry 10
* Navigateur
* iOS
* Paciarelli
* Windows Phone 7 et 8
* Windows 8
### Petit exemple
// Android: Froyo OS would return "2.2"
// Eclair OS would return "2.1", "2.0.1", or "2.0"
// Version can also return update level "2.1-update1"
//
// BlackBerry: Torch 9800 using OS 6.0 would return "6.0.0.600"
//
// Browser: Returns version number for the browser
//
// iPhone: iOS 3.2 returns "3.2"
//
// Windows Phone 7: returns current OS version number, ex. on Mango returns 7.10.7720
// Tizen: returns "TIZEN_20120425_2"
var deviceVersion = device.version;
\ No newline at end of file
<!---
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.
-->
# org.apache.cordova.device
Questo plugin definisce un global `device` oggetto che descrive il dispositivo hardware e software. Sebbene l'oggetto sia in ambito globale, non è disponibile fino a dopo il `deviceready` evento.
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
console.log(device.cordova);
}
## Installazione
cordova plugin add org.apache.cordova.device
## Proprietà
* device.cordova
* device.model
* device.platform
* device.uuid
* device.version
## device.cordova
Ottenere la versione di Cordova in esecuzione nel dispositivo.
### Piattaforme supportate
* Amazon fuoco OS
* Android
* BlackBerry 10
* Browser
* Firefox OS
* iOS
* Tizen
* Windows Phone 7 e 8
* Windows 8
## device.model
Il `device.model` restituisce il nome del modello del dispositivo o del prodotto. Il valore viene impostato dal produttore del dispositivo e può essere differente tra le versioni dello stesso prodotto.
### Piattaforme supportate
* Android
* BlackBerry 10
* Browser
* iOS
* Tizen
* Windows Phone 7 e 8
* Windows 8
### Esempio rapido
// Android: Nexus One returns "Passion" (Nexus One code name)
// Motorola Droid returns "voles"
// BlackBerry: Torch 9800 returns "9800"
// Browser: Google Chrome returns "Chrome"
// Safari returns "Safari"
// iOS: for the iPad Mini, returns iPad2,5; iPhone 5 is iPhone 5,1. Vedi http://theiphonewiki.com/wiki/index.php?title=Models / / modello var = device.model;
### Stranezze Android
* Ottiene il [nome del prodotto][1] anziché il [nome del modello][2], che è spesso il nome di codice di produzione. Ad esempio, restituisce il Nexus One `Passion` , e Motorola Droid restituisce`voles`.
[1]: http://developer.android.com/reference/android/os/Build.html#PRODUCT
[2]: http://developer.android.com/reference/android/os/Build.html#MODEL
### Tizen stranezze
* Restituisce il modello di dispositivo assegnato dal fornitore, ad esempio,`TIZEN`
### Windows Phone 7 e 8 stranezze
* Restituisce il modello di dispositivo specificato dal produttore. Ad esempio, restituisce il Samsung Focus`SGH-i917`.
## device.platform
Ottenere il nome del sistema operativo del dispositivo.
var string = device.platform;
### Piattaforme supportate
* Android
* BlackBerry 10
* Browser4
* Firefox OS
* iOS
* Tizen
* Windows Phone 7 e 8
* Windows 8
### Esempio rapido
// Depending on the device, a few examples are:
// - "Android"
// - "BlackBerry 10"
// - Browser: returns "MacIntel" on Mac
// returns "Win32" on Windows
// - "iOS"
// - "WinCE"
// - "Tizen"
var devicePlatform = device.platform;
### Windows Phone 7 capricci
Windows Phone 7 dispositivi segnalano la piattaforma come`WinCE`.
### Windows Phone 8 stranezze
Dispositivi Windows Phone 8 segnalano la piattaforma come`Win32NT`.
## device.uuid
Ottenere identificatore del dispositivo univoco universale ([UUID][3]).
[3]: http://en.wikipedia.org/wiki/Universally_Unique_Identifier
var string = device.uuid;
### Descrizione
I dettagli di come viene generato un UUID sono determinati dal produttore del dispositivo e sono specifici per la piattaforma o il modello del dispositivo.
### Piattaforme supportate
* Android
* BlackBerry 10
* iOS
* Tizen
* Windows Phone 7 e 8
* Windows 8
### Esempio rapido
/ / Android: restituisce un intero casuale di 64 bit (come stringa, ancora una volta!) / / il numero intero è generato al primo avvio del dispositivo / / / / BlackBerry: restituisce il numero PIN del dispositivo / / questo è un valore integer univoco a nove cifre (come stringa, benchè!) / / / / iPhone: (parafrasato dalla documentazione della classe UIDevice) / / restituisce una stringa di valori hash creata dall'hardware più identifica.
/ / È garantito per essere unica per ogni dispositivo e non può essere legato / / per l'account utente.
/ / Windows Phone 7: restituisce un hash dell'utente corrente, + dispositivo / / se l'utente non è definito, un guid generato e persisterà fino a quando l'applicazione viene disinstallata / / Tizen: restituisce il dispositivo IMEI (International Mobile Equipment Identity o IMEI è un numero / / unico per ogni cellulare GSM e UMTS.
var deviceID = device.uuid;
### iOS Quirk
Il `uuid` su iOS non è univoco per un dispositivo, ma varia per ogni applicazione, per ogni installazione. Cambia se si elimina e re-installare l'app, e possibilmente anche quando aggiornare iOS o anche aggiornare l'app per ogni versione (apparente in iOS 5.1). Il `uuid` non è un valore affidabile.
### Windows Phone 7 e 8 stranezze
Il `uuid` per Windows Phone 7 richiede l'autorizzazione `ID_CAP_IDENTITY_DEVICE` . Microsoft probabilmente sarà presto deprecare questa proprietà. Se la funzionalità non è disponibile, l'applicazione genera un guid persistente che viene mantenuto per la durata dell'installazione dell'applicazione sul dispositivo.
## device.version
Ottenere la versione del sistema operativo.
var string = device.version;
### Piattaforme supportate
* Android 2.1 +
* BlackBerry 10
* Browser
* iOS
* Tizen
* Windows Phone 7 e 8
* Windows 8
### Esempio rapido
// Android: Froyo OS would return "2.2"
// Eclair OS would return "2.1", "2.0.1", or "2.0"
// Version can also return update level "2.1-update1"
//
// BlackBerry: Torch 9800 using OS 6.0 would return "6.0.0.600"
//
// Browser: Returns version number for the browser
//
// iPhone: iOS 3.2 returns "3.2"
//
// Windows Phone 7: returns current OS version number, ex. on Mango returns 7.10.7720
// Tizen: returns "TIZEN_20120425_2"
var deviceVersion = device.version;
\ No newline at end of file
<!---
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.
-->
# org.apache.cordova.device
このプラグインをグローバル定義します `device` オブジェクトは、デバイスのハードウェアとソフトウェアについて説明します。 それは後まで利用可能なオブジェクトがグローバル スコープでは、 `deviceready` イベント。
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
console.log(device.cordova);
}
## インストール
cordova plugin add org.apache.cordova.device
## プロパティ
* device.cordova
* device.model
* device.platform
* device.uuid
* device.version
## device.cordova
デバイスで実行されているコルドバのバージョンを取得します。
### サポートされているプラットフォーム
* アマゾン火 OS
* アンドロイド
* ブラックベリー 10
* ブラウザー
* Firefox の OS
* iOS
* Tizen
* Windows Phone 7 と 8
* Windows 8
## device.model
`device.model`、デバイスのモデルまたは製品の名前を返します。値は、デバイスの製造元によって設定され、同じ製品のバージョン間で異なる可能性があります。
### サポートされているプラットフォーム
* アンドロイド
* ブラックベリー 10
* ブラウザー
* iOS
* Tizen
* Windows Phone 7 と 8
* Windows 8
### 簡単な例
// Android: Nexus One returns "Passion" (Nexus One code name)
// Motorola Droid returns "voles"
// BlackBerry: Torch 9800 returns "9800"
// Browser: Google Chrome returns "Chrome"
// Safari returns "Safari"
// iOS: for the iPad Mini, returns iPad2,5; iPhone 5 is iPhone 5,1. Http://theiphonewiki.com/wiki/index.php?title=Models を参照してください//var モデル = device.model;
### Android の癖
* 生産コード名は[モデル名][1]の代わりに[製品名][2]を取得します。 たとえば、ネクサス 1 つを返します `Passion` 、Motorola のドロイドを返します`voles`.
[1]: http://developer.android.com/reference/android/os/Build.html#MODEL
[2]: http://developer.android.com/reference/android/os/Build.html#PRODUCT
### Tizen の癖
* たとえば、ベンダーによって割り当てられているデバイスのモデルを返します`TIZEN`
### Windows Phone 7 と 8 癖
* 製造元によって指定されたデバイスのモデルを返します。たとえば、三星フォーカスを返します`SGH-i917`.
## device.platform
デバイスのオペレーティング システム名を取得します。
var string = device.platform;
### サポートされているプラットフォーム
* アンドロイド
* ブラックベリー 10
* Browser4
* Firefox の OS
* iOS
* Tizen
* Windows Phone 7 と 8
* Windows 8
### 簡単な例
// Depending on the device, a few examples are:
// - "Android"
// - "BlackBerry 10"
// - Browser: returns "MacIntel" on Mac
// returns "Win32" on Windows
// - "iOS"
// - "WinCE"
// - "Tizen"
var devicePlatform = device.platform;
### Windows Phone 7 の癖
Windows Phone 7 デバイスとプラットフォームを報告します。`WinCE`.
### Windows Phone 8 癖
Windows Phone 8 デバイスとプラットフォームを報告します。`Win32NT`.
## device.uuid
デバイスのユニバーサル ・ ユニーク識別子 ([UUID][3]を取得します。).
[3]: http://en.wikipedia.org/wiki/Universally_Unique_Identifier
var string = device.uuid;
### 説明
UUID を生成する方法の詳細は、デバイスの製造元によって決定され、デバイスのプラットフォームやモデルに固有です。
### サポートされているプラットフォーム
* アンドロイド
* ブラックベリー 10
* iOS
* Tizen
* Windows Phone 7 と 8
* Windows 8
### 簡単な例
//アンドロイド: ランダムな 64 ビットの整数 (を文字列として返します、再び !)/デバイスの最初の起動時に生成される整数/////ブラックベリー: デバイスのピン番号を返します//これは 9 桁の一意な整数 (を文字列としても !)////iPhone: (UIDevice クラスのドキュメントから言い換え)//識別複数のハードウェアから作成されたハッシュ値の文字列を返します。。
//それはすべてのデバイスに対して一意であることが保証され、接続することはできません//ユーザー アカウント。
//Windows Phone 7: デバイス + 現在のユーザーのハッシュを返します//ユーザーが定義されていない場合 guid が生成され、アプリがアンインストールされるまで保持されます//Tizen: デバイスの IMEI を返します (国際モバイル機器アイデンティティまたは IMEI は番号です//すべての GSM および UMTS の携帯電話に固有です。
var deviceID = device.uuid;
### iOS の気まぐれ
`uuid`IOS で、デバイスに固有ではないインストールごと、アプリケーションごとに異なります。 削除、アプリを再インストールした場合に変更と多分またときアップグレード iOS の, またはもアップグレードするアプリ (iOS の 5.1 で明らかに) バージョンごと。 `uuid`は信頼性の高い値ではありません。
### Windows Phone 7 と 8 癖
`uuid`のために Windows Phone 7 には、権限が必要です `ID_CAP_IDENTITY_DEVICE` 。 Microsoft はすぐにこのプロパティを廃止して可能性があります。 機能が利用できない場合、アプリケーションはデバイスへのアプリケーションのインストールの持続期間のために保持されている永続的な guid を生成します。
## device.version
オペレーティング システムのバージョンを取得します。
var string = device.version;
### サポートされているプラットフォーム
* アンドロイド 2.1 +
* ブラックベリー 10
* ブラウザー
* iOS
* Tizen
* Windows Phone 7 と 8
* Windows 8
### 簡単な例
// Android: Froyo OS would return "2.2"
// Eclair OS would return "2.1", "2.0.1", or "2.0"
// Version can also return update level "2.1-update1"
//
// BlackBerry: Torch 9800 using OS 6.0 would return "6.0.0.600"
//
// Browser: Returns version number for the browser
//
// iPhone: iOS 3.2 returns "3.2"
//
// Windows Phone 7: returns current OS version number, ex. on Mango returns 7.10.7720
// Tizen: returns "TIZEN_20120425_2"
var deviceVersion = device.version;
\ No newline at end of file
<!---
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.
-->
# org.apache.cordova.device
이 플러그인 정의 전역 `device` 개체, 디바이스의 하드웨어 및 소프트웨어에 설명 합니다. 개체는 전역 범위에서 비록 그것은 후까지 사용할 수 있는 `deviceready` 이벤트.
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
console.log(device.cordova);
}
## 설치
cordova plugin add org.apache.cordova.device
## 속성
* device.cordova
* device.model
* device.platform
* device.uuid
* device.version
## device.cordova
코르도바는 장치에서 실행 중인 버전을 얻을.
### 지원 되는 플랫폼
* 아마존 화재 운영 체제
* 안 드 로이드
* 블랙베리 10
* 브라우저
* Firefox 운영 체제
* iOS
* Tizen
* Windows Phone 7과 8
* 윈도우 8
## device.model
`device.model`소자의 모델 또는 제품의 이름을 반환 합니다. 값 장치 제조업체에서 설정 되 고 동일 제품의 버전 간에 다를 수 있습니다.
### 지원 되는 플랫폼
* 안 드 로이드
* 블랙베리 10
* 브라우저
* iOS
* Tizen
* Windows Phone 7과 8
* 윈도우 8
### 빠른 예제
// Android: Nexus One returns "Passion" (Nexus One code name)
// Motorola Droid returns "voles"
// BlackBerry: Torch 9800 returns "9800"
// Browser: Google Chrome returns "Chrome"
// Safari returns "Safari"
// iOS: for the iPad Mini, returns iPad2,5; iPhone 5 is iPhone 5,1. Http://theiphonewiki.com/wiki/index.php?title=Models 참조 / / var 모델 = device.model;
### 안 드 로이드 단점
* 어떤은 종종 프로덕션 코드 이름 대신 [제품 모델 이름][1], [제품 이름][2] 을 가져옵니다. 예를 들어 넥서스 하나 반환 합니다 `Passion` , 모토로라 Droid를 반환 합니다`voles`.
[1]: http://developer.android.com/reference/android/os/Build.html#MODEL
[2]: http://developer.android.com/reference/android/os/Build.html#PRODUCT
### Tizen 특수
* 예를 들어, 공급 업체에 의해 할당 된 디바이스 모델을 반환 합니다.`TIZEN`
### Windows Phone 7, 8 특수
* 제조업체에서 지정 하는 장치 모델을 반환 합니다. 예를 들어 삼성 포커스를 반환 합니다.`SGH-i917`.
## device.platform
장치의 운영 체제 이름을 얻을.
var string = device.platform;
### 지원 되는 플랫폼
* 안 드 로이드
* 블랙베리 10
* Browser4
* Firefox 운영 체제
* iOS
* Tizen
* Windows Phone 7과 8
* 윈도우 8
### 빠른 예제
// Depending on the device, a few examples are:
// - "Android"
// - "BlackBerry 10"
// - Browser: returns "MacIntel" on Mac
// returns "Win32" on Windows
// - "iOS"
// - "WinCE"
// - "Tizen"
var devicePlatform = device.platform;
### Windows Phone 7 단점
Windows Phone 7 장치 보고 플랫폼으로`WinCE`.
### Windows Phone 8 단점
Windows Phone 8 장치 보고 플랫폼으로`Win32NT`.
## device.uuid
소자의 보편적으로 고유 식별자 ([UUID][3] 를 얻을합니다).
[3]: http://en.wikipedia.org/wiki/Universally_Unique_Identifier
var string = device.uuid;
### 설명
UUID 생성 방법의 자세한 내용은 장치 제조업체에 의해 결정 됩니다 및 소자의 플랫폼 이나 모델.
### 지원 되는 플랫폼
* 안 드 로이드
* 블랙베리 10
* iOS
* Tizen
* Windows Phone 7과 8
* 윈도우 8
### 빠른 예제
/ / 안 드 로이드: (문자열로 다시!) 임의의 64 비트 정수를 반환 합니다 / / 정수 장치의 첫 번째 부팅에서 생성 / / / / 블랙베리: 디바이스의 핀 번호를 반환 합니다 / / 이것은 9 자리 고유 정수 (문자열로 비록!) / / / / 아이폰: (UIDevice 클래스 설명서에서 읊 었) / / 문자열 여러 하드웨어에서 생성 하는 해시 값을 식별 하는 반환 합니다.
/ 그것은 모든 장치에 대 한 고유 해야 보장 되 고 묶일 수 없습니다 / / / 사용자 계정에.
/ / Windows Phone 7: 장치 + 현재 사용자의 해시를 반환 합니다 / / 사용자 정의 되지 않은 경우 guid 생성 되 고 응용 프로그램을 제거할 때까지 유지 됩니다 / / Tizen: 반환 장치 IMEI (국제 모바일 기기 식별 또는 IMEI 숫자입니다 / / 모든 GSM와 UMTS 휴대 전화 고유.
var deviceID = device.uuid;
### iOS 특질
`uuid`ios 장치에 고유 하지 않습니다 하지만 각 설치에 대 한 응용 프로그램 마다 다릅니다. 삭제 하 고 다시 애플 리 케이 션을 설치 하는 경우 변경 가능 하 게 또한 iOS를 업그레이드 하거나 때 버전 (iOS 5.1에에서 명백한) 당 응용 프로그램 업그레이드도 하 고. `uuid`은 신뢰할 수 있는 값이 아닙니다.
### Windows Phone 7, 8 특수
`uuid`Windows Phone 7 필요 허가 `ID_CAP_IDENTITY_DEVICE` . Microsoft는 곧이 속성을 세웁니다 가능성이 것입니다. 기능을 사용할 수 없는 경우 응용 프로그램 장치에 응용 프로그램의 설치 하는 동안 유지 하는 영구 guid를 생성 합니다.
## device.version
운영 체제 버전을 얻을.
var string = device.version;
### 지원 되는 플랫폼
* 안 드 로이드 2.1 +
* 블랙베리 10
* 브라우저
* iOS
* Tizen
* Windows Phone 7과 8
* 윈도우 8
### 빠른 예제
// Android: Froyo OS would return "2.2"
// Eclair OS would return "2.1", "2.0.1", or "2.0"
// Version can also return update level "2.1-update1"
//
// BlackBerry: Torch 9800 using OS 6.0 would return "6.0.0.600"
//
// Browser: Returns version number for the browser
//
// iPhone: iOS 3.2 returns "3.2"
//
// Windows Phone 7: returns current OS version number, ex. on Mango returns 7.10.7720
// Tizen: returns "TIZEN_20120425_2"
var deviceVersion = device.version;
\ No newline at end of file
<!---
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.
-->
# org.apache.cordova.device
Ten plugin określa globalne `device` obiekt, który opisuje urządzenia sprzętowe i programowe. Mimo, że obiekt jest w globalnym zasięgu, nie jest dostępne dopiero po `deviceready` zdarzenie.
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
console.log(device.cordova);
}
## Instalacja
cordova plugin add org.apache.cordova.device
## Właściwości
* device.cordova
* device.model
* device.platform
* device.uuid
* device.version
## device.cordova
Pobierz wersję Cordova działa na urządzeniu.
### Obsługiwane platformy
* Amazon Fire OS
* Android
* BlackBerry 10
* Przeglądarka
* Firefox OS
* iOS
* Tizen
* Windows Phone 7 i 8
* Windows 8
## device.model
`device.model`Zwraca nazwę modelu lub produktu. Wartość jest zestaw przez producenta urządzenia i mogą się różnić między wersjami tego samego produktu.
### Obsługiwane platformy
* Android
* BlackBerry 10
* Przeglądarka
* iOS
* Tizen
* Windows Phone 7 i 8
* Windows 8
### Szybki przykład
// Android: Nexus One returns "Passion" (Nexus One code name)
// Motorola Droid returns "voles"
// BlackBerry: Torch 9800 returns "9800"
// Browser: Google Chrome returns "Chrome"
// Safari returns "Safari"
// iOS: for the iPad Mini, returns iPad2,5; iPhone 5 is iPhone 5,1. Zobacz http://theiphonewiki.com/wiki/index.php?title=Models / / modelu var = device.model;
### Dziwactwa Androida
* Pobiera [nazwę produktu][1] zamiast [nazwy modelu][2], który często jest nazwą kod produkcji. Na przykład, Nexus One zwraca `Passion` , i zwraca Motorola Droid`voles`.
[1]: http://developer.android.com/reference/android/os/Build.html#PRODUCT
[2]: http://developer.android.com/reference/android/os/Build.html#MODEL
### Dziwactwa Tizen
* Zwraca modelu urządzenia przypisane przez dostawcę, na przykład,`TIZEN`
### Windows Phone 7 i 8 dziwactwa
* Zwraca modelu urządzenia, określonej przez producenta. Na przykład Samsung ostrości zwraca`SGH-i917`.
## device.platform
Uzyskać nazwę systemu operacyjnego urządzenia.
var string = device.platform;
### Obsługiwane platformy
* Android
* BlackBerry 10
* Browser4
* Firefox OS
* iOS
* Tizen
* Windows Phone 7 i 8
* Windows 8
### Szybki przykład
// Depending on the device, a few examples are:
// - "Android"
// - "BlackBerry 10"
// - Browser: returns "MacIntel" on Mac
// returns "Win32" on Windows
// - "iOS"
// - "WinCE"
// - "Tizen"
var devicePlatform = device.platform;
### Dziwactwa Windows Phone 7
Urządzenia Windows Phone 7 raport platformy jako`WinCE`.
### Windows Phone 8 dziwactwa
Urządzenia Windows Phone 8 raport platformy jako`Win32NT`.
## device.uuid
Się urządzenia uniwersalnie unikatowy identyfikator ([UUID][3]).
[3]: http://en.wikipedia.org/wiki/Universally_Unique_Identifier
var string = device.uuid;
### Opis
Szczegóły jak UUID jest generowane są określane przez producenta urządzenia i są specyficzne dla platformy lub modelu urządzenia.
### Obsługiwane platformy
* Android
* BlackBerry 10
* iOS
* Tizen
* Windows Phone 7 i 8
* Windows 8
### Szybki przykład
/ / Android: zwraca losowe 64-bitowa liczba całkowita (jako ciąg, znowu!) / / liczba całkowita jest generowany na pierwszego uruchomienia urządzenia / / / / BlackBerry: zwraca numer PIN urządzenia / / to jest unikatową liczbą całkowitą dziewięciu cyfr (jako ciąg, choć!) / / / / iPhone: (zacytowana w dokumentacji klasy UIDevice) / / zwraca ciąg wartości mieszania utworzone z wielu sprzętu identyfikuje.
Zapewniona jest unikatowy dla każdego urządzenia i nie może być związane z / do konta użytkownika.
/ / Windows Phone 7: zwraca wartość mieszania urządzenia + bieżący użytkownik, / / jeśli nie zdefiniowane przez użytkownika, identyfikator guid jest generowany i będzie trwać do czasu odinstalowania aplikacji / / Tizen: zwraca urządzenia IMEI (International Mobile Equipment Identity lub IMEI jest liczbą / / unikatowe dla każdego telefonu komórkowego GSM i UMTS.
var deviceID = device.uuid;
### iOS dziwactwo
`uuid`Na iOS nie jest przypisany do urządzenia, ale różni się dla każdej aplikacji, dla każdej instalacji. Zmienia się jeśli możesz usunąć i ponownie zainstalować aplikację, a ewentualnie także po aktualizacji iOS czy nawet uaktualnienia aplikacji dla wersji (widoczny w iOS 5.1). `uuid`Jest nie wiarygodne wartości.
### Windows Phone 7 i 8 dziwactwa
`uuid`Dla Windows Phone 7 wymaga uprawnień `ID_CAP_IDENTITY_DEVICE` . Microsoft będzie prawdopodobnie potępiać ten wkrótce. Jeśli funkcja nie jest dostępna, aplikacja generuje trwałe identyfikator guid, który jest utrzymywany przez czas trwania instalacji aplikacji na urządzeniu.
## device.version
Pobierz wersję systemu operacyjnego.
var string = device.version;
### Obsługiwane platformy
* Android 2.1 +
* BlackBerry 10
* Przeglądarka
* iOS
* Tizen
* Windows Phone 7 i 8
* Windows 8
### Szybki przykład
// Android: Froyo OS would return "2.2"
// Eclair OS would return "2.1", "2.0.1", or "2.0"
// Version can also return update level "2.1-update1"
//
// BlackBerry: Torch 9800 using OS 6.0 would return "6.0.0.600"
//
// Browser: Returns version number for the browser
//
// iPhone: iOS 3.2 returns "3.2"
//
// Windows Phone 7: returns current OS version number, ex. on Mango returns 7.10.7720
// Tizen: returns "TIZEN_20120425_2"
var deviceVersion = device.version;
\ No newline at end of file
<!---
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.
-->
# org.apache.cordova.device
Этот плагин определяет глобальный объект `device`, который описывает оборудование и программное обеспечение устройства. Несмотря на то что объект в глобальной области видимости, он не доступен до того момента пока не произойдет событие `deviceready`.
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
console.log(device.cordova);
}
## Установка
cordova plugin add org.apache.cordova.device
## Параметры
* device.cordova
* device.model
* device.platform
* device.uuid
* device.version
## device.cordova
Возвращает версию Cordova, работающую на устройстве.
### Поддерживаемые платформы
* Amazon Fire OS
* Android
* BlackBerry 10
* Обозреватель
* Firefox OS
* iOS
* Tizen
* Windows Phone 7 и 8
* Windows 8
## device.model
Свойство `device.model` возвращает имя устройства модели или продукта. Значение устанавливается производителем устройства и могут отличаться в разных версиях одного и того же продукта.
### Поддерживаемые платформы
* Android
* BlackBerry 10
* Обозреватель
* iOS
* Tizen
* Windows Phone 7 и 8
* Windows 8
### Краткий пример
// Android: Nexus One returns "Passion" (Nexus One code name)
// Motorola Droid returns "voles"
// BlackBerry: Torch 9800 returns "9800"
// Browser: Google Chrome returns "Chrome"
// Safari returns "Safari"
// iOS: for the iPad Mini, returns iPad2,5; iPhone 5 is iPhone 5,1. See http://theiphonewiki.com/wiki/index.php?title=Models
//
var model = device.model;
### Особенности Android
* Возвращает [имя продукта][1] , а не [имя модели][2], которое часто является производственным кодом. Например, Nexus One из них возвращает `Passion` , и Motorola Droid возвращает `voles`.
[1]: http://developer.android.com/reference/android/os/Build.html#PRODUCT
[2]: http://developer.android.com/reference/android/os/Build.html#MODEL
### Особенности Tizen
* Возвращает модель устройства, назначенного вендором, например,`TIZEN`
### Особенности Windows Phone 7 и 8
* Возвращает модель устройства, указанной заводом-изготовителем. Например Samsung Focus возвращает `SGH-i917`.
## device.platform
Получите имя операционной системы устройства.
var string = device.platform;
### Поддерживаемые платформы
* Android
* BlackBerry 10
* Браузером4
* Firefox OS
* iOS
* Tizen
* Windows Phone 7 и 8
* Windows 8
### Краткий пример
// Depending on the device, a few examples are:
// - "Android"
// - "BlackBerry 10"
// - Browser: returns "MacIntel" on Mac
// returns "Win32" on Windows
// - "iOS"
// - "WinCE"
// - "Tizen"
var devicePlatform = device.platform;
### Особенности Windows Phone 7
Windows Phone 7 устройства сообщают платформу как `WinCE`.
### Особенности Windows Phone 8
Устройства Windows Phone 8 сообщают платформу как `Win32NT`.
## device.uuid
Возвращает универсальный уникального идентификатора ([UUID][3] устройства).
[3]: http://en.wikipedia.org/wiki/Universally_Unique_Identifier
var string = device.uuid;
### Описание
Подробная информация о том как UUID генерируется, определяются изготовителем устройства и являются специфическими для платформы или модели устройства.
### Поддерживаемые платформы
* Android
* BlackBerry 10
* iOS
* Tizen
* Windows Phone 7 и 8
* Windows 8
### Краткий пример
// Android: Возвращает случайное 64-разрядное целое число (в виде строки, опять!)
// целое число генерируется при первой загрузке устройства
//
// BlackBerry: Возвращает номер PIN устройства
// это 9 значный уникальный целочисленный (как строка, хотя!)
//
// iPhone: (Перефразировано из документации класса UIDevice)
// возвращает строку хэш-значения, созданные из нескольких аппаратных определяет.
// Это значение гарантированно является уникальным для каждого устройства и не может быть привязано
// к учетной записи пользователя.
// Windows Phone 7: Возвращает хэш устройство + текущего пользователя,
// если пользователь не определен, формируется guid который и будет сохраняться до тех пор, пока приложение не удалиться
// Tizen: возвращает IMEI устройства (Международный идентификатор мобильного оборудования или IMEI это число
// уникальное для каждого мобильного телефона GSM и UMTS.
var deviceID = device.uuid;
### Особенности iOS
На iOS `uuid` не является уникальным для устройства, но варьируется для каждого приложения, и для каждой установки. Значение меняется, если удалить и повторно установить приложение, и возможно также когда вы обновите iOS, или даже обновить приложение до следующей версии (очевидно в iOS 5.1). Значение `uuid` не является надежным.
### Особенности Windows Phone 7 и 8
Для Windows Phone 7 `uuid` требует разрешения `ID_CAP_IDENTITY_DEVICE` . Microsoft скорее всего скоро сделает это свойство устаревшим. Если возможность недоступна, приложение создает постоянные guid, который сохраняется на все время установки приложения на устройстве.
## device.version
Возвращает версию операционной системы.
var string = device.version;
### Поддерживаемые платформы
* Android 2.1 +
* BlackBerry 10
* Обозреватель
* iOS
* Tizen
* Windows Phone 7 и 8
* Windows 8
### Краткий пример
// Android: Froyo OS would return "2.2"
// Eclair OS would return "2.1", "2.0.1", or "2.0"
// Version can also return update level "2.1-update1"
//
// BlackBerry: Torch 9800 using OS 6.0 would return "6.0.0.600"
//
// Browser: Returns version number for the browser
//
// iPhone: iOS 3.2 returns "3.2"
//
// Windows Phone 7: returns current OS version number, ex. on Mango returns 7.10.7720
// Tizen: returns "TIZEN_20120425_2"
var deviceVersion = device.version;
\ No newline at end of file
<!---
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.
-->
# org.apache.cordova.device
這個外掛程式定義全球 `device` 物件,描述該設備的硬體和軟體。 雖然物件是在全球範圍內,但不是可用,直到後 `deviceready` 事件。
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
console.log(device.cordova);
}
## 安裝
cordova plugin add org.apache.cordova.device
## 屬性
* device.cordova
* device.model
* device.platform
* device.uuid
* device.version
## device.cordova
獲取科爾多瓦在設備上運行的版本。
### 支援的平臺
* 亞馬遜火 OS
* Android 系統
* 黑莓 10
* 瀏覽器
* 火狐瀏覽器的作業系統
* iOS
* 泰
* Windows Phone 7 和 8
* Windows 8
## device.model
`device.model`返回設備的模型或產品的名稱。值由設備製造商設置和同一產品的不同版本可能不同。
### 支援的平臺
* Android 系統
* 黑莓 10
* 瀏覽器
* iOS
* 泰
* Windows Phone 7 和 8
* Windows 8
### 快速的示例
// Android: Nexus One returns "Passion" (Nexus One code name)
// Motorola Droid returns "voles"
// BlackBerry: Torch 9800 returns "9800"
// Browser: Google Chrome returns "Chrome"
// Safari returns "Safari"
// iOS: for the iPad Mini, returns iPad2,5; iPhone 5 is iPhone 5,1. 請參閱 HTTP://theiphonewiki.com/wiki/index.php?title=Models / / var 模型 = device.model ;
### Android 的怪癖
* 獲取[產品名稱][1]而不是[產品型號名稱][2],這往往是生產代碼名稱。 例如,Nexus One 返回 `Passion` ,和摩托羅拉 Droid 返回`voles`.
[1]: http://developer.android.com/reference/android/os/Build.html#PRODUCT
[2]: http://developer.android.com/reference/android/os/Build.html#MODEL
### Tizen 怪癖
* 例如,返回與供應商指派的設備模型`TIZEN`
### Windows Phone 7 和 8 怪癖
* 返回由製造商指定的設備模型。例如,三星焦點返回`SGH-i917`.
## device.platform
獲取設備的作業系統名稱。
var string = device.platform;
### 支援的平臺
* Android 系統
* 黑莓 10
* Browser4
* 火狐瀏覽器的作業系統
* iOS
* 泰
* Windows Phone 7 和 8
* Windows 8
### 快速的示例
// Depending on the device, a few examples are:
// - "Android"
// - "BlackBerry 10"
// - Browser: returns "MacIntel" on Mac
// returns "Win32" on Windows
// - "iOS"
// - "WinCE"
// - "Tizen"
var devicePlatform = device.platform;
### Windows Phone 7 的怪癖
Windows Phone 7 設備報告作為平臺`WinCE`.
### Windows Phone 8 怪癖
Windows Phone 8 設備報告作為平臺`Win32NT`.
## device.uuid
獲取設備的通用唯一識別碼 ([UUID][3]).
[3]: http://en.wikipedia.org/wiki/Universally_Unique_Identifier
var string = device.uuid;
### 說明
如何生成一個 UUID 的細節由設備製造商和特定于設備的平臺或模型。
### 支援的平臺
* Android 系統
* 黑莓 10
* iOS
* Tizen
* Windows Phone 7 和 8
* Windows 8
### 快速的示例
/ / Android: 一個隨機的 64 位整數 (作為字串返回,再次!) / / 上設備的第一次啟動生成的整數 / / / / 黑莓手機: 返回設備的 PIN 號碼 / / 這是九個數字的唯一整數 (作為字串,雖然!) / / / / iPhone: (從 UIDevice 類文檔解釋) / / 返回一個字串的雜湊值創建的多個硬體標識。
/ / 它保證是唯一的每個設備並不能綁 / / 到使用者帳戶。
/ / Windows Phone 7: 返回的雜湊代碼的設備 + 當前使用者,/ / 如果未定義使用者,則一個 guid 生成的並且將會保留直到卸載該應用程式 / / Tizen: 返回設備 IMEI (國際行動裝置身份或 IMEI 是一個數位 / / 獨有的每一個 UMTS 和 GSM 行動電話。
var deviceID = device.uuid;
### iOS 怪癖
`uuid`在 iOS 不是唯一的一種裝置,但對於每個應用程式,為每個安裝而異。 如果您刪除並重新安裝該應用程式,它更改和可能還當你升級 iOS,或甚至升級每個版本 (iOS 5.1 中存在明顯的) 的應用程式。 `uuid`不是一個可靠的值。
### Windows Phone 7 和 8 怪癖
`uuid`為 Windows Phone 7 須經許可 `ID_CAP_IDENTITY_DEVICE` 。 Microsoft 可能會很快棄用此屬性。 如果沒有可用的能力,應用程式將生成設備上應用程式的安裝過程中保持持續的 guid。
## device.version
獲取作業系統版本。
var string = device.version;
### 支援的平臺
* Android 2.1 +
* 黑莓 10
* 瀏覽器
* iOS
* 泰
* Windows Phone 7 和 8
* Windows 8
### 快速的示例
// Android: Froyo OS would return "2.2"
// Eclair OS would return "2.1", "2.0.1", or "2.0"
// Version can also return update level "2.1-update1"
//
// BlackBerry: Torch 9800 using OS 6.0 would return "6.0.0.600"
//
// Browser: Returns version number for the browser
//
// iPhone: iOS 3.2 returns "3.2"
//
// Windows Phone 7: returns current OS version number, ex. on Mango returns 7.10.7720
// Tizen: returns "TIZEN_20120425_2"
var deviceVersion = device.version;
\ No newline at end of file
{
"version": "0.3.0",
"name": "org.apache.cordova.device",
"cordova_name": "Device",
"description": "Cordova Device Plugin",
"license": "Apache 2.0",
"repo": "https://git-wip-us.apache.org/repos/asf/cordova-plugin-device.git",
"issue": "https://issues.apache.org/jira/browse/CB/component/12320648",
"keywords": [
"cordova",
"device"
],
"platforms": [
"firefoxos",
"tizen",
"android",
"amazon-fireos",
"ubuntu",
"ios",
"blackberry10",
"wp7",
"wp8",
"windows8",
"windows",
"browser"
],
"engines": [],
"englishdoc": "<!---\n Licensed to the Apache Software Foundation (ASF) under one\n or more contributor license agreements. See the NOTICE file\n distributed with this work for additional information\n regarding copyright ownership. The ASF licenses this file\n to you under the Apache License, Version 2.0 (the\n \"License\"); you may not use this file except in compliance\n with the License. You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing,\n software distributed under the License is distributed on an\n \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n KIND, either express or implied. See the License for the\n specific language governing permissions and limitations\n under the License.\n-->\n\n# org.apache.cordova.device\n\nThis plugin defines a global `device` object, which describes the device's hardware and software.\nAlthough the object is in the global scope, it is not available until after the `deviceready` event.\n\n document.addEventListener(\"deviceready\", onDeviceReady, false);\n function onDeviceReady() {\n console.log(device.cordova);\n }\n\n## Installation\n\n cordova plugin add org.apache.cordova.device\n\n## Properties\n\n- device.cordova\n- device.model\n- device.platform\n- device.uuid\n- device.version\n\n## device.cordova\n\nGet the version of Cordova running on the device.\n\n### Supported Platforms\n\n- Amazon Fire OS\n- Android\n- BlackBerry 10\n- Browser\n- Firefox OS\n- iOS\n- Tizen\n- Windows Phone 7 and 8\n- Windows 8\n\n## device.model\n\nThe `device.model` returns the name of the device's model or\nproduct. The value is set by the device manufacturer and may be\ndifferent across versions of the same product.\n\n### Supported Platforms\n\n- Android\n- BlackBerry 10\n- Browser\n- iOS\n- Tizen\n- Windows Phone 7 and 8\n- Windows 8\n\n### Quick Example\n\n // Android: Nexus One returns \"Passion\" (Nexus One code name)\n // Motorola Droid returns \"voles\"\n // BlackBerry: Torch 9800 returns \"9800\"\n // Browser: Google Chrome returns \"Chrome\"\n // Safari returns \"Safari\"\n // iOS: for the iPad Mini, returns iPad2,5; iPhone 5 is iPhone 5,1. See http://theiphonewiki.com/wiki/index.php?title=Models\n //\n var model = device.model;\n\n### Android Quirks\n\n- Gets the [product name](http://developer.android.com/reference/android/os/Build.html#PRODUCT) instead of the [model name](http://developer.android.com/reference/android/os/Build.html#MODEL), which is often the production code name. For example, the Nexus One returns `Passion`, and Motorola Droid returns `voles`.\n\n### Tizen Quirks\n\n- Returns the device model assigned by the vendor, for example, `TIZEN`\n\n### Windows Phone 7 and 8 Quirks\n\n- Returns the device model specified by the manufacturer. For example, the Samsung Focus returns `SGH-i917`.\n\n## device.platform\n\nGet the device's operating system name.\n\n var string = device.platform;\n\n### Supported Platforms\n\n- Android\n- BlackBerry 10\n- Browser4\n- Firefox OS\n- iOS\n- Tizen\n- Windows Phone 7 and 8\n- Windows 8\n\n### Quick Example\n\n // Depending on the device, a few examples are:\n // - \"Android\"\n // - \"BlackBerry 10\"\n // - Browser: returns \"MacIntel\" on Mac\n // returns \"Win32\" on Windows\n // - \"iOS\"\n // - \"WinCE\"\n // - \"Tizen\"\n var devicePlatform = device.platform;\n\n### Windows Phone 7 Quirks\n\nWindows Phone 7 devices report the platform as `WinCE`.\n\n### Windows Phone 8 Quirks\n\nWindows Phone 8 devices report the platform as `Win32NT`.\n\n## device.uuid\n\nGet the device's Universally Unique Identifier ([UUID](http://en.wikipedia.org/wiki/Universally_Unique_Identifier)).\n\n var string = device.uuid;\n\n### Description\n\nThe details of how a UUID is generated are determined by the device manufacturer and are specific to the device's platform or model.\n\n### Supported Platforms\n\n- Android\n- BlackBerry 10\n- iOS\n- Tizen\n- Windows Phone 7 and 8\n- Windows 8\n\n### Quick Example\n\n // Android: Returns a random 64-bit integer (as a string, again!)\n // The integer is generated on the device's first boot\n //\n // BlackBerry: Returns the PIN number of the device\n // This is a nine-digit unique integer (as a string, though!)\n //\n // iPhone: (Paraphrased from the UIDevice Class documentation)\n // Returns a string of hash values created from multiple hardware identifies.\n // It is guaranteed to be unique for every device and can't be tied\n // to the user account.\n // Windows Phone 7 : Returns a hash of device+current user,\n // if the user is not defined, a guid is generated and will persist until the app is uninstalled\n // Tizen: returns the device IMEI (International Mobile Equipment Identity or IMEI is a number\n // unique to every GSM and UMTS mobile phone.\n var deviceID = device.uuid;\n\n### iOS Quirk\n\nThe `uuid` on iOS is not unique to a device, but varies for each\napplication, for each installation. It changes if you delete and\nre-install the app, and possibly also when you upgrade iOS, or even\nupgrade the app per version (apparent in iOS 5.1). The `uuid` is not\na reliable value.\n\n### Windows Phone 7 and 8 Quirks\n\nThe `uuid` for Windows Phone 7 requires the permission\n`ID_CAP_IDENTITY_DEVICE`. Microsoft will likely deprecate this\nproperty soon. If the capability is not available, the application\ngenerates a persistent guid that is maintained for the duration of the\napplication's installation on the device.\n\n## device.version\n\nGet the operating system version.\n\n var string = device.version;\n\n### Supported Platforms\n\n- Android 2.1+\n- BlackBerry 10\n- Browser\n- iOS\n- Tizen\n- Windows Phone 7 and 8\n- Windows 8\n\n### Quick Example\n\n // Android: Froyo OS would return \"2.2\"\n // Eclair OS would return \"2.1\", \"2.0.1\", or \"2.0\"\n // Version can also return update level \"2.1-update1\"\n //\n // BlackBerry: Torch 9800 using OS 6.0 would return \"6.0.0.600\"\n //\n // Browser: Returns version number for the browser\n //\n // iPhone: iOS 3.2 returns \"3.2\"\n //\n // Windows Phone 7: returns current OS version number, ex. on Mango returns 7.10.7720\n // Tizen: returns \"TIZEN_20120425_2\"\n var deviceVersion = device.version;\n\n"
}
\ No newline at end of file
/*
*
* 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.
*
*/
var cordova = require('cordova');
var utils = require('cordova/utils');
module.exports = {
getDeviceInfo:function(win,fail,args) {
// deviceId aka uuid, stored in Windows.Storage.ApplicationData.current.localSettings.values.deviceId
var deviceId;
var localSettings = Windows.Storage.ApplicationData.current.localSettings;
if (localSettings.values.deviceId) {
deviceId = localSettings.values.deviceId;
}
else {
// App-specific hardware id could be used as uuid, but it changes if the hardware changes...
try {
var ASHWID = Windows.System.Profile.HardwareIdentification.getPackageSpecificToken(null).id;
deviceId = Windows.Storage.Streams.DataReader.fromBuffer(ASHWID).readGuid();
} catch (e) {
// Couldn't get the hardware UUID
deviceId = createUUID();
}
//...so cache it per-install
localSettings.values.deviceId = deviceId;
}
var versionString = window.clientInformation.userAgent.match(/Windows NT ([0-9.]+)/)[1];
(function(self){
var ROOT_CONTAINER = "{00000000-0000-0000-FFFF-FFFFFFFFFFFF}";
var DEVICE_CLASS_KEY = "{A45C254E-DF1C-4EFD-8020-67D146A850E0},10";
var DEVICE_CLASS_KEY_NO_SEMICOLON = '{A45C254E-DF1C-4EFD-8020-67D146A850E0}10';
var ROOT_CONTAINER_QUERY = "System.Devices.ContainerId:=\"" + ROOT_CONTAINER + "\"";
var HAL_DEVICE_CLASS = "4d36e966-e325-11ce-bfc1-08002be10318";
var DEVICE_DRIVER_VERSION_KEY = "{A8B865DD-2E3D-4094-AD97-E593A70C75D6},3";
var pnpObject = Windows.Devices.Enumeration.Pnp.PnpObject;
pnpObject.findAllAsync(Windows.Devices.Enumeration.Pnp.PnpObjectType.device, [DEVICE_DRIVER_VERSION_KEY, DEVICE_CLASS_KEY], ROOT_CONTAINER_QUERY).then(function(rootDevices) {
for (var i = 0; i < rootDevices.length; i++) {
var rootDevice = rootDevices[i];
if (!rootDevice.properties) continue;
if (rootDevice.properties[DEVICE_CLASS_KEY_NO_SEMICOLON] == HAL_DEVICE_CLASS) {
versionString = rootDevice.properties[DEVICE_DRIVER_VERSION_KEY];
break;
}
}
setTimeout(function () {
win({ platform: "windows8", version: versionString, uuid: deviceId, model: window.clientInformation.platform });
}, 0);
});
})(this);
}
};
require("cordova/exec/proxy").add("Device", module.exports);
......@@ -21,7 +21,7 @@
}
},
"dependent_plugins": {
"org.apache.cordova.device": {
"cordova-plugin-device": {
"PACKAGE_NAME": "NotificationExample"
}
}
......
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