mirror of
https://github.com/apache/cordova-android.git
synced 2025-05-11 22:04:56 +08:00
CB-9782 Implements PlatformApi contract for Android platform.
This closes #226
This commit is contained in:
parent
789c505a88
commit
400282282f
@ -1,6 +1,8 @@
|
|||||||
language: android
|
language: android
|
||||||
sudo: false
|
sudo: false
|
||||||
install:
|
install:
|
||||||
|
- "(pushd .. && git clone https://github.com/apache/cordova-lib.git && popd)"
|
||||||
|
- npm link ../cordova-lib/cordova-common
|
||||||
- npm install
|
- npm install
|
||||||
- echo y | android update sdk -u --filter android-23
|
- echo y | android update sdk -u --filter android-23
|
||||||
script:
|
script:
|
||||||
|
105
bin/create
105
bin/create
@ -1,49 +1,56 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Licensed to the Apache Software Foundation (ASF) under one
|
Licensed to the Apache Software Foundation (ASF) under one
|
||||||
or more contributor license agreements. See the NOTICE file
|
or more contributor license agreements. See the NOTICE file
|
||||||
distributed with this work for additional information
|
distributed with this work for additional information
|
||||||
regarding copyright ownership. The ASF licenses this file
|
regarding copyright ownership. The ASF licenses this file
|
||||||
to you under the Apache License, Version 2.0 (the
|
to you under the Apache License, Version 2.0 (the
|
||||||
"License"); you may not use this file except in compliance
|
"License"); you may not use this file except in compliance
|
||||||
with the License. You may obtain a copy of the License at
|
with the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing,
|
Unless required by applicable law or agreed to in writing,
|
||||||
software distributed under the License is distributed on an
|
software distributed under the License is distributed on an
|
||||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
KIND, either express or implied. See the License for the
|
KIND, either express or implied. See the License for the
|
||||||
specific language governing permissions and limitations
|
specific language governing permissions and limitations
|
||||||
under the License.
|
under the License.
|
||||||
*/
|
*/
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
var create = require('./lib/create');
|
var ConfigParser = require('cordova-common').ConfigParser;
|
||||||
var argv = require('nopt')({
|
var Api = require('./templates/cordova/Api');
|
||||||
'help' : Boolean,
|
|
||||||
'cli' : Boolean,
|
var argv = require('nopt')({
|
||||||
'shared' : Boolean,
|
'help' : Boolean,
|
||||||
'link' : Boolean,
|
'cli' : Boolean,
|
||||||
'activity-name' : [String, undefined]
|
'shared' : Boolean,
|
||||||
});
|
'link' : Boolean,
|
||||||
|
'activity-name' : [String, undefined]
|
||||||
if (argv.help || argv.argv.remain.length === 0) {
|
});
|
||||||
console.log('Usage: ' + path.relative(process.cwd(), path.join(__dirname, 'create')) + ' <path_to_new_project> <package_name> <project_name> [<template_path>] [--activity-name <activity_name>] [--link]');
|
|
||||||
console.log(' <path_to_new_project>: Path to your new Cordova Android project');
|
if (argv.help || argv.argv.remain.length === 0) {
|
||||||
console.log(' <package_name>: Package name, following reverse-domain style convention');
|
console.log('Usage: ' + path.relative(process.cwd(), path.join(__dirname, 'create')) + ' <path_to_new_project> <package_name> <project_name> [<template_path>] [--activity-name <activity_name>] [--link]');
|
||||||
console.log(' <project_name>: Project name');
|
console.log(' <path_to_new_project>: Path to your new Cordova Android project');
|
||||||
console.log(' <template_path>: Path to a custom application template to use');
|
console.log(' <package_name>: Package name, following reverse-domain style convention');
|
||||||
console.log(' --activity-name <activity_name>: Activity name');
|
console.log(' <project_name>: Project name');
|
||||||
console.log(' --link will use the CordovaLib project directly instead of making a copy.');
|
console.log(' <template_path>: Path to a custom application template to use');
|
||||||
process.exit(1);
|
console.log(' --activity-name <activity_name>: Activity name');
|
||||||
}
|
console.log(' --link will use the CordovaLib project directly instead of making a copy.');
|
||||||
|
process.exit(1);
|
||||||
var project_path = argv.argv.remain[0];
|
}
|
||||||
var package_name = argv.argv.remain[1];
|
|
||||||
var project_name = argv.argv.remain[2];
|
var config = new ConfigParser(path.resolve(__dirname, 'templates/project/res/xml/config.xml'));
|
||||||
var template_path = argv.argv.remain[3];
|
|
||||||
var activity_name = argv['activity-name'];
|
if (argv.argv.remain[1]) config.setPackageName(argv.argv.remain[1]);
|
||||||
|
if (argv.argv.remain[2]) config.setName(argv.argv.remain[2]);
|
||||||
create.createProject(project_path, package_name, project_name, activity_name, template_path, argv.link || argv.shared, argv.cli).done();
|
if (argv['activity-name']) config.setName(argv['activity-name']);
|
||||||
|
|
||||||
|
var options = {
|
||||||
|
link: argv.link || argv.shared,
|
||||||
|
customTemplate: argv.argv.remain[3],
|
||||||
|
activityName: argv['activity-name']
|
||||||
|
};
|
||||||
|
|
||||||
|
Api.createPlatform(argv.argv.remain[0], config, options).done();
|
||||||
|
@ -1,327 +1,326 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Licensed to the Apache Software Foundation (ASF) under one
|
Licensed to the Apache Software Foundation (ASF) under one
|
||||||
or more contributor license agreements. See the NOTICE file
|
or more contributor license agreements. See the NOTICE file
|
||||||
distributed with this work for additional information
|
distributed with this work for additional information
|
||||||
regarding copyright ownership. The ASF licenses this file
|
regarding copyright ownership. The ASF licenses this file
|
||||||
to you under the Apache License, Version 2.0 (the
|
to you under the Apache License, Version 2.0 (the
|
||||||
"License"); you may not use this file except in compliance
|
"License"); you may not use this file except in compliance
|
||||||
with the License. You may obtain a copy of the License at
|
with the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing,
|
Unless required by applicable law or agreed to in writing,
|
||||||
software distributed under the License is distributed on an
|
software distributed under the License is distributed on an
|
||||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
KIND, either express or implied. See the License for the
|
KIND, either express or implied. See the License for the
|
||||||
specific language governing permissions and limitations
|
specific language governing permissions and limitations
|
||||||
under the License.
|
under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* jshint sub:true */
|
/* jshint sub:true */
|
||||||
|
|
||||||
var shelljs = require('shelljs'),
|
var shelljs = require('shelljs'),
|
||||||
child_process = require('child_process'),
|
child_process = require('child_process'),
|
||||||
Q = require('q'),
|
Q = require('q'),
|
||||||
path = require('path'),
|
path = require('path'),
|
||||||
fs = require('fs'),
|
fs = require('fs'),
|
||||||
which = require('which'),
|
ROOT = path.join(__dirname, '..', '..');
|
||||||
ROOT = path.join(__dirname, '..', '..');
|
var CordovaError = require('cordova-common').CordovaError;
|
||||||
|
|
||||||
var isWindows = process.platform == 'win32';
|
var isWindows = process.platform == 'win32';
|
||||||
|
|
||||||
function forgivingWhichSync(cmd) {
|
function forgivingWhichSync(cmd) {
|
||||||
try {
|
try {
|
||||||
// TODO: Should use shelljs.which() here to have one less dependency.
|
return fs.realpathSync(shelljs.which(cmd));
|
||||||
return fs.realpathSync(which.sync(cmd));
|
} catch (e) {
|
||||||
} catch (e) {
|
return '';
|
||||||
return '';
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
function tryCommand(cmd, errMsg, catchStderr) {
|
||||||
function tryCommand(cmd, errMsg, catchStderr) {
|
var d = Q.defer();
|
||||||
var d = Q.defer();
|
child_process.exec(cmd, function(err, stdout, stderr) {
|
||||||
child_process.exec(cmd, function(err, stdout, stderr) {
|
if (err) d.reject(new CordovaError(errMsg));
|
||||||
if (err) d.reject(new Error(errMsg));
|
// Sometimes it is necessary to return an stderr instead of stdout in case of success, since
|
||||||
// Sometimes it is necessary to return an stderr instead of stdout in case of success, since
|
// some commands prints theirs output to stderr instead of stdout. 'javac' is the example
|
||||||
// some commands prints theirs output to stderr instead of stdout. 'javac' is the example
|
else d.resolve((catchStderr ? stderr : stdout).trim());
|
||||||
else d.resolve((catchStderr ? stderr : stdout).trim());
|
});
|
||||||
});
|
return d.promise;
|
||||||
return d.promise;
|
}
|
||||||
}
|
|
||||||
|
// Get valid target from framework/project.properties
|
||||||
// Get valid target from framework/project.properties
|
module.exports.get_target = function() {
|
||||||
module.exports.get_target = function() {
|
function extractFromFile(filePath) {
|
||||||
function extractFromFile(filePath) {
|
var target = shelljs.grep(/\btarget=/, filePath);
|
||||||
var target = shelljs.grep(/\btarget=/, filePath);
|
if (!target) {
|
||||||
if (!target) {
|
throw new Error('Could not find android target within: ' + filePath);
|
||||||
throw new Error('Could not find android target within: ' + filePath);
|
}
|
||||||
}
|
return target.split('=')[1].trim();
|
||||||
return target.split('=')[1].trim();
|
}
|
||||||
}
|
if (fs.existsSync(path.join(ROOT, 'framework', 'project.properties'))) {
|
||||||
if (fs.existsSync(path.join(ROOT, 'framework', 'project.properties'))) {
|
return extractFromFile(path.join(ROOT, 'framework', 'project.properties'));
|
||||||
return extractFromFile(path.join(ROOT, 'framework', 'project.properties'));
|
}
|
||||||
}
|
if (fs.existsSync(path.join(ROOT, 'project.properties'))) {
|
||||||
if (fs.existsSync(path.join(ROOT, 'project.properties'))) {
|
// if no target found, we're probably in a project and project.properties is in ROOT.
|
||||||
// if no target found, we're probably in a project and project.properties is in ROOT.
|
return extractFromFile(path.join(ROOT, 'project.properties'));
|
||||||
return extractFromFile(path.join(ROOT, 'project.properties'));
|
}
|
||||||
}
|
throw new Error('Could not find android target. File missing: ' + path.join(ROOT, 'project.properties'));
|
||||||
throw new Error('Could not find android target. File missing: ' + path.join(ROOT, 'project.properties'));
|
};
|
||||||
};
|
|
||||||
|
// Returns a promise. Called only by build and clean commands.
|
||||||
// Returns a promise. Called only by build and clean commands.
|
module.exports.check_ant = function() {
|
||||||
module.exports.check_ant = function() {
|
return tryCommand('ant -version', 'Failed to run "ant -version", make sure you have ant installed and added to your PATH.')
|
||||||
return tryCommand('ant -version', 'Failed to run "ant -version", make sure you have ant installed and added to your PATH.')
|
.then(function (output) {
|
||||||
.then(function (output) {
|
// Parse Ant version from command output
|
||||||
// Parse Ant version from command output
|
return /version ((?:\d+\.)+(?:\d+))/i.exec(output)[1];
|
||||||
return /version ((?:\d+\.)+(?:\d+))/i.exec(output)[1];
|
});
|
||||||
});
|
};
|
||||||
};
|
|
||||||
|
// Returns a promise. Called only by build and clean commands.
|
||||||
// Returns a promise. Called only by build and clean commands.
|
module.exports.check_gradle = function() {
|
||||||
module.exports.check_gradle = function() {
|
var sdkDir = process.env['ANDROID_HOME'];
|
||||||
var sdkDir = process.env['ANDROID_HOME'];
|
if (!sdkDir)
|
||||||
if (!sdkDir)
|
return Q.reject(new CordovaError('Could not find gradle wrapper within Android SDK. Could not find Android SDK directory.\n' +
|
||||||
return Q.reject('Could not find gradle wrapper within Android SDK. Could not find Android SDK directory.\n' +
|
'Might need to install Android SDK or set up \'ANDROID_HOME\' env variable.'));
|
||||||
'Might need to install Android SDK or set up \'ANDROID_HOME\' env variable.');
|
|
||||||
|
var wrapperDir = path.join(sdkDir, 'tools', 'templates', 'gradle', 'wrapper');
|
||||||
var wrapperDir = path.join(sdkDir, 'tools', 'templates', 'gradle', 'wrapper');
|
if (!fs.existsSync(wrapperDir)) {
|
||||||
if (!fs.existsSync(wrapperDir)) {
|
return Q.reject(new CordovaError('Could not find gradle wrapper within Android SDK. Might need to update your Android SDK.\n' +
|
||||||
return Q.reject(new Error('Could not find gradle wrapper within Android SDK. Might need to update your Android SDK.\n' +
|
'Looked here: ' + wrapperDir));
|
||||||
'Looked here: ' + wrapperDir));
|
}
|
||||||
}
|
return Q.when();
|
||||||
return Q.when();
|
};
|
||||||
};
|
|
||||||
|
// Returns a promise.
|
||||||
// Returns a promise.
|
module.exports.check_java = function() {
|
||||||
module.exports.check_java = function() {
|
var javacPath = forgivingWhichSync('javac');
|
||||||
var javacPath = forgivingWhichSync('javac');
|
var hasJavaHome = !!process.env['JAVA_HOME'];
|
||||||
var hasJavaHome = !!process.env['JAVA_HOME'];
|
return Q().then(function() {
|
||||||
return Q().then(function() {
|
if (hasJavaHome) {
|
||||||
if (hasJavaHome) {
|
// Windows java installer doesn't add javac to PATH, nor set JAVA_HOME (ugh).
|
||||||
// Windows java installer doesn't add javac to PATH, nor set JAVA_HOME (ugh).
|
if (!javacPath) {
|
||||||
if (!javacPath) {
|
process.env['PATH'] += path.delimiter + path.join(process.env['JAVA_HOME'], 'bin');
|
||||||
process.env['PATH'] += path.delimiter + path.join(process.env['JAVA_HOME'], 'bin');
|
}
|
||||||
}
|
} else {
|
||||||
} else {
|
if (javacPath) {
|
||||||
if (javacPath) {
|
var msg = 'Failed to find \'JAVA_HOME\' environment variable. Try setting setting it manually.';
|
||||||
var msg = 'Failed to find \'JAVA_HOME\' environment variable. Try setting setting it manually.';
|
// OS X has a command for finding JAVA_HOME.
|
||||||
// OS X has a command for finding JAVA_HOME.
|
if (fs.existsSync('/usr/libexec/java_home')) {
|
||||||
if (fs.existsSync('/usr/libexec/java_home')) {
|
return tryCommand('/usr/libexec/java_home', msg)
|
||||||
return tryCommand('/usr/libexec/java_home', msg)
|
.then(function(stdout) {
|
||||||
.then(function(stdout) {
|
process.env['JAVA_HOME'] = stdout.trim();
|
||||||
process.env['JAVA_HOME'] = stdout.trim();
|
});
|
||||||
});
|
} else {
|
||||||
} else {
|
// See if we can derive it from javac's location.
|
||||||
// See if we can derive it from javac's location.
|
// fs.realpathSync is require on Ubuntu, which symplinks from /usr/bin -> JDK
|
||||||
// fs.realpathSync is require on Ubuntu, which symplinks from /usr/bin -> JDK
|
var maybeJavaHome = path.dirname(path.dirname(javacPath));
|
||||||
var maybeJavaHome = path.dirname(path.dirname(javacPath));
|
if (fs.existsSync(path.join(maybeJavaHome, 'lib', 'tools.jar'))) {
|
||||||
if (fs.existsSync(path.join(maybeJavaHome, 'lib', 'tools.jar'))) {
|
process.env['JAVA_HOME'] = maybeJavaHome;
|
||||||
process.env['JAVA_HOME'] = maybeJavaHome;
|
} else {
|
||||||
} else {
|
throw new CordovaError(msg);
|
||||||
throw new Error(msg);
|
}
|
||||||
}
|
}
|
||||||
}
|
} else if (isWindows) {
|
||||||
} else if (isWindows) {
|
// Try to auto-detect java in the default install paths.
|
||||||
// Try to auto-detect java in the default install paths.
|
var oldSilent = shelljs.config.silent;
|
||||||
var oldSilent = shelljs.config.silent;
|
shelljs.config.silent = true;
|
||||||
shelljs.config.silent = true;
|
var firstJdkDir =
|
||||||
var firstJdkDir =
|
shelljs.ls(process.env['ProgramFiles'] + '\\java\\jdk*')[0] ||
|
||||||
shelljs.ls(process.env['ProgramFiles'] + '\\java\\jdk*')[0] ||
|
shelljs.ls('C:\\Program Files\\java\\jdk*')[0] ||
|
||||||
shelljs.ls('C:\\Program Files\\java\\jdk*')[0] ||
|
shelljs.ls('C:\\Program Files (x86)\\java\\jdk*')[0];
|
||||||
shelljs.ls('C:\\Program Files (x86)\\java\\jdk*')[0];
|
shelljs.config.silent = oldSilent;
|
||||||
shelljs.config.silent = oldSilent;
|
if (firstJdkDir) {
|
||||||
if (firstJdkDir) {
|
// shelljs always uses / in paths.
|
||||||
// shelljs always uses / in paths.
|
firstJdkDir = firstJdkDir.replace(/\//g, path.sep);
|
||||||
firstJdkDir = firstJdkDir.replace(/\//g, path.sep);
|
if (!javacPath) {
|
||||||
if (!javacPath) {
|
process.env['PATH'] += path.delimiter + path.join(firstJdkDir, 'bin');
|
||||||
process.env['PATH'] += path.delimiter + path.join(firstJdkDir, 'bin');
|
}
|
||||||
}
|
process.env['JAVA_HOME'] = firstJdkDir;
|
||||||
process.env['JAVA_HOME'] = firstJdkDir;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}).then(function() {
|
||||||
}).then(function() {
|
var msg =
|
||||||
var msg =
|
'Failed to run "java -version", make sure that you have a JDK installed.\n' +
|
||||||
'Failed to run "java -version", make sure that you have a JDK installed.\n' +
|
'You can get it from: http://www.oracle.com/technetwork/java/javase/downloads.\n';
|
||||||
'You can get it from: http://www.oracle.com/technetwork/java/javase/downloads.\n';
|
if (process.env['JAVA_HOME']) {
|
||||||
if (process.env['JAVA_HOME']) {
|
msg += 'Your JAVA_HOME is invalid: ' + process.env['JAVA_HOME'] + '\n';
|
||||||
msg += 'Your JAVA_HOME is invalid: ' + process.env['JAVA_HOME'] + '\n';
|
}
|
||||||
}
|
return tryCommand('java -version', msg)
|
||||||
return tryCommand('java -version', msg)
|
.then(function() {
|
||||||
.then(function() {
|
// We use tryCommand with catchStderr = true, because
|
||||||
// We use tryCommand with catchStderr = true, because
|
// javac writes version info to stderr instead of stdout
|
||||||
// javac writes version info to stderr instead of stdout
|
return tryCommand('javac -version', msg, true);
|
||||||
return tryCommand('javac -version', msg, true);
|
}).then(function (output) {
|
||||||
}).then(function (output) {
|
var match = /javac ((?:\d+\.)+(?:\d+))/i.exec(output)[1];
|
||||||
var match = /javac ((?:\d+\.)+(?:\d+))/i.exec(output)[1];
|
return match && match[1];
|
||||||
return match && match[1];
|
});
|
||||||
});
|
});
|
||||||
});
|
};
|
||||||
};
|
|
||||||
|
// Returns a promise.
|
||||||
// Returns a promise.
|
module.exports.check_android = function() {
|
||||||
module.exports.check_android = function() {
|
return Q().then(function() {
|
||||||
return Q().then(function() {
|
var androidCmdPath = forgivingWhichSync('android');
|
||||||
var androidCmdPath = forgivingWhichSync('android');
|
var adbInPath = !!forgivingWhichSync('adb');
|
||||||
var adbInPath = !!forgivingWhichSync('adb');
|
var hasAndroidHome = !!process.env['ANDROID_HOME'] && fs.existsSync(process.env['ANDROID_HOME']);
|
||||||
var hasAndroidHome = !!process.env['ANDROID_HOME'] && fs.existsSync(process.env['ANDROID_HOME']);
|
function maybeSetAndroidHome(value) {
|
||||||
function maybeSetAndroidHome(value) {
|
if (!hasAndroidHome && fs.existsSync(value)) {
|
||||||
if (!hasAndroidHome && fs.existsSync(value)) {
|
hasAndroidHome = true;
|
||||||
hasAndroidHome = true;
|
process.env['ANDROID_HOME'] = value;
|
||||||
process.env['ANDROID_HOME'] = value;
|
}
|
||||||
}
|
}
|
||||||
}
|
if (!hasAndroidHome && !androidCmdPath) {
|
||||||
if (!hasAndroidHome && !androidCmdPath) {
|
if (isWindows) {
|
||||||
if (isWindows) {
|
// Android Studio 1.0 installer
|
||||||
// Android Studio 1.0 installer
|
maybeSetAndroidHome(path.join(process.env['LOCALAPPDATA'], 'Android', 'sdk'));
|
||||||
maybeSetAndroidHome(path.join(process.env['LOCALAPPDATA'], 'Android', 'sdk'));
|
maybeSetAndroidHome(path.join(process.env['ProgramFiles'], 'Android', 'sdk'));
|
||||||
maybeSetAndroidHome(path.join(process.env['ProgramFiles'], 'Android', 'sdk'));
|
// Android Studio pre-1.0 installer
|
||||||
// Android Studio pre-1.0 installer
|
maybeSetAndroidHome(path.join(process.env['LOCALAPPDATA'], 'Android', 'android-studio', 'sdk'));
|
||||||
maybeSetAndroidHome(path.join(process.env['LOCALAPPDATA'], 'Android', 'android-studio', 'sdk'));
|
maybeSetAndroidHome(path.join(process.env['ProgramFiles'], 'Android', 'android-studio', 'sdk'));
|
||||||
maybeSetAndroidHome(path.join(process.env['ProgramFiles'], 'Android', 'android-studio', 'sdk'));
|
// Stand-alone installer
|
||||||
// Stand-alone installer
|
maybeSetAndroidHome(path.join(process.env['LOCALAPPDATA'], 'Android', 'android-sdk'));
|
||||||
maybeSetAndroidHome(path.join(process.env['LOCALAPPDATA'], 'Android', 'android-sdk'));
|
maybeSetAndroidHome(path.join(process.env['ProgramFiles'], 'Android', 'android-sdk'));
|
||||||
maybeSetAndroidHome(path.join(process.env['ProgramFiles'], 'Android', 'android-sdk'));
|
} else if (process.platform == 'darwin') {
|
||||||
} else if (process.platform == 'darwin') {
|
// Android Studio 1.0 installer
|
||||||
// Android Studio 1.0 installer
|
maybeSetAndroidHome(path.join(process.env['HOME'], 'Library', 'Android', 'sdk'));
|
||||||
maybeSetAndroidHome(path.join(process.env['HOME'], 'Library', 'Android', 'sdk'));
|
// Android Studio pre-1.0 installer
|
||||||
// Android Studio pre-1.0 installer
|
maybeSetAndroidHome('/Applications/Android Studio.app/sdk');
|
||||||
maybeSetAndroidHome('/Applications/Android Studio.app/sdk');
|
// Stand-alone zip file that user might think to put under /Applications
|
||||||
// Stand-alone zip file that user might think to put under /Applications
|
maybeSetAndroidHome('/Applications/android-sdk-macosx');
|
||||||
maybeSetAndroidHome('/Applications/android-sdk-macosx');
|
maybeSetAndroidHome('/Applications/android-sdk');
|
||||||
maybeSetAndroidHome('/Applications/android-sdk');
|
}
|
||||||
}
|
if (process.env['HOME']) {
|
||||||
if (process.env['HOME']) {
|
// Stand-alone zip file that user might think to put under their home directory
|
||||||
// Stand-alone zip file that user might think to put under their home directory
|
maybeSetAndroidHome(path.join(process.env['HOME'], 'android-sdk-macosx'));
|
||||||
maybeSetAndroidHome(path.join(process.env['HOME'], 'android-sdk-macosx'));
|
maybeSetAndroidHome(path.join(process.env['HOME'], 'android-sdk'));
|
||||||
maybeSetAndroidHome(path.join(process.env['HOME'], 'android-sdk'));
|
}
|
||||||
}
|
}
|
||||||
}
|
if (hasAndroidHome && !androidCmdPath) {
|
||||||
if (hasAndroidHome && !androidCmdPath) {
|
process.env['PATH'] += path.delimiter + path.join(process.env['ANDROID_HOME'], 'tools');
|
||||||
process.env['PATH'] += path.delimiter + path.join(process.env['ANDROID_HOME'], 'tools');
|
}
|
||||||
}
|
if (androidCmdPath && !hasAndroidHome) {
|
||||||
if (androidCmdPath && !hasAndroidHome) {
|
var parentDir = path.dirname(androidCmdPath);
|
||||||
var parentDir = path.dirname(androidCmdPath);
|
var grandParentDir = path.dirname(parentDir);
|
||||||
var grandParentDir = path.dirname(parentDir);
|
if (path.basename(parentDir) == 'tools') {
|
||||||
if (path.basename(parentDir) == 'tools') {
|
process.env['ANDROID_HOME'] = path.dirname(parentDir);
|
||||||
process.env['ANDROID_HOME'] = path.dirname(parentDir);
|
hasAndroidHome = true;
|
||||||
hasAndroidHome = true;
|
} else if (fs.existsSync(path.join(grandParentDir, 'tools', 'android'))) {
|
||||||
} else if (fs.existsSync(path.join(grandParentDir, 'tools', 'android'))) {
|
process.env['ANDROID_HOME'] = grandParentDir;
|
||||||
process.env['ANDROID_HOME'] = grandParentDir;
|
hasAndroidHome = true;
|
||||||
hasAndroidHome = true;
|
} else {
|
||||||
} else {
|
throw new CordovaError('Failed to find \'ANDROID_HOME\' environment variable. Try setting setting it manually.\n' +
|
||||||
throw new Error('Failed to find \'ANDROID_HOME\' environment variable. Try setting setting it manually.\n' +
|
'Detected \'android\' command at ' + parentDir + ' but no \'tools\' directory found near.\n' +
|
||||||
'Detected \'android\' command at ' + parentDir + ' but no \'tools\' directory found near.\n' +
|
'Try reinstall Android SDK or update your PATH to include path to valid SDK directory.');
|
||||||
'Try reinstall Android SDK or update your PATH to include path to valid SDK directory.');
|
}
|
||||||
}
|
}
|
||||||
}
|
if (hasAndroidHome && !adbInPath) {
|
||||||
if (hasAndroidHome && !adbInPath) {
|
process.env['PATH'] += path.delimiter + path.join(process.env['ANDROID_HOME'], 'platform-tools');
|
||||||
process.env['PATH'] += path.delimiter + path.join(process.env['ANDROID_HOME'], 'platform-tools');
|
}
|
||||||
}
|
if (!process.env['ANDROID_HOME']) {
|
||||||
if (!process.env['ANDROID_HOME']) {
|
throw new CordovaError('Failed to find \'ANDROID_HOME\' environment variable. Try setting setting it manually.\n' +
|
||||||
throw new Error('Failed to find \'ANDROID_HOME\' environment variable. Try setting setting it manually.\n' +
|
'Failed to find \'android\' command in your \'PATH\'. Try update your \'PATH\' to include path to valid SDK directory.');
|
||||||
'Failed to find \'android\' command in your \'PATH\'. Try update your \'PATH\' to include path to valid SDK directory.');
|
}
|
||||||
}
|
if (!fs.existsSync(process.env['ANDROID_HOME'])) {
|
||||||
if (!fs.existsSync(process.env['ANDROID_HOME'])) {
|
throw new CordovaError('\'ANDROID_HOME\' environment variable is set to non-existent path: ' + process.env['ANDROID_HOME'] +
|
||||||
throw new Error('\'ANDROID_HOME\' environment variable is set to non-existent path: ' + process.env['ANDROID_HOME'] +
|
'\nTry update it manually to point to valid SDK directory.');
|
||||||
'\nTry update it manually to point to valid SDK directory.');
|
}
|
||||||
}
|
});
|
||||||
});
|
};
|
||||||
};
|
|
||||||
|
module.exports.getAbsoluteAndroidCmd = function() {
|
||||||
module.exports.getAbsoluteAndroidCmd = function() {
|
return forgivingWhichSync('android').replace(/(\s)/g, '\\$1');
|
||||||
return forgivingWhichSync('android').replace(/(\s)/g, '\\$1');
|
};
|
||||||
};
|
|
||||||
|
module.exports.check_android_target = function(valid_target) {
|
||||||
module.exports.check_android_target = function(valid_target) {
|
// valid_target can look like:
|
||||||
// valid_target can look like:
|
// android-19
|
||||||
// android-19
|
// android-L
|
||||||
// android-L
|
// Google Inc.:Google APIs:20
|
||||||
// Google Inc.:Google APIs:20
|
// Google Inc.:Glass Development Kit Preview:20
|
||||||
// Google Inc.:Glass Development Kit Preview:20
|
if (!valid_target) valid_target = module.exports.get_target();
|
||||||
if (!valid_target) valid_target = module.exports.get_target();
|
var msg = 'Android SDK not found. Make sure that it is installed. If it is not at the default location, set the ANDROID_HOME environment variable.';
|
||||||
var msg = 'Android SDK not found. Make sure that it is installed. If it is not at the default location, set the ANDROID_HOME environment variable.';
|
return tryCommand('android list targets --compact', msg)
|
||||||
return tryCommand('android list targets --compact', msg)
|
.then(function(output) {
|
||||||
.then(function(output) {
|
var targets = output.split('\n');
|
||||||
var targets = output.split('\n');
|
if (targets.indexOf(valid_target) >= 0) {
|
||||||
if (targets.indexOf(valid_target) >= 0) {
|
return targets;
|
||||||
return targets;
|
}
|
||||||
}
|
|
||||||
|
var androidCmd = module.exports.getAbsoluteAndroidCmd();
|
||||||
var androidCmd = module.exports.getAbsoluteAndroidCmd();
|
throw new CordovaError('Please install Android target: "' + valid_target + '".\n\n' +
|
||||||
throw new Error('Please install Android target: "' + valid_target + '".\n\n' +
|
'Hint: Open the SDK manager by running: ' + androidCmd + '\n' +
|
||||||
'Hint: Open the SDK manager by running: ' + androidCmd + '\n' +
|
'You will require:\n' +
|
||||||
'You will require:\n' +
|
'1. "SDK Platform" for ' + valid_target + '\n' +
|
||||||
'1. "SDK Platform" for ' + valid_target + '\n' +
|
'2. "Android SDK Platform-tools (latest)\n' +
|
||||||
'2. "Android SDK Platform-tools (latest)\n' +
|
'3. "Android SDK Build-tools" (latest)');
|
||||||
'3. "Android SDK Build-tools" (latest)');
|
});
|
||||||
});
|
};
|
||||||
};
|
|
||||||
|
// Returns a promise.
|
||||||
// Returns a promise.
|
module.exports.run = function() {
|
||||||
module.exports.run = function() {
|
return Q.all([this.check_java(), this.check_android().then(this.check_android_target)])
|
||||||
return Q.all([this.check_java(), this.check_android().then(this.check_android_target)])
|
.then(function() {
|
||||||
.then(function() {
|
console.log('ANDROID_HOME=' + process.env['ANDROID_HOME']);
|
||||||
console.log('ANDROID_HOME=' + process.env['ANDROID_HOME']);
|
console.log('JAVA_HOME=' + process.env['JAVA_HOME']);
|
||||||
console.log('JAVA_HOME=' + process.env['JAVA_HOME']);
|
});
|
||||||
});
|
};
|
||||||
};
|
|
||||||
|
/**
|
||||||
/**
|
* Object thar represents one of requirements for current platform.
|
||||||
* Object thar represents one of requirements for current platform.
|
* @param {String} id The unique identifier for this requirements.
|
||||||
* @param {String} id The unique identifier for this requirements.
|
* @param {String} name The name of requirements. Human-readable field.
|
||||||
* @param {String} name The name of requirements. Human-readable field.
|
* @param {String} version The version of requirement installed. In some cases could be an array of strings
|
||||||
* @param {String} version The version of requirement installed. In some cases could be an array of strings
|
* (for example, check_android_target returns an array of android targets installed)
|
||||||
* (for example, check_android_target returns an array of android targets installed)
|
* @param {Boolean} installed Indicates whether the requirement is installed or not
|
||||||
* @param {Boolean} installed Indicates whether the requirement is installed or not
|
*/
|
||||||
*/
|
var Requirement = function (id, name, version, installed) {
|
||||||
var Requirement = function (id, name, version, installed) {
|
this.id = id;
|
||||||
this.id = id;
|
this.name = name;
|
||||||
this.name = name;
|
this.installed = installed || false;
|
||||||
this.installed = installed || false;
|
this.metadata = {
|
||||||
this.metadata = {
|
version: version,
|
||||||
version: version,
|
};
|
||||||
};
|
};
|
||||||
};
|
|
||||||
|
/**
|
||||||
/**
|
* Methods that runs all checks one by one and returns a result of checks
|
||||||
* 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
|
||||||
* 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.
|
||||||
* @return Promise<Requirement[]> Array of requirements. Due to implementation, promise is always fulfilled.
|
*/
|
||||||
*/
|
module.exports.check_all = function() {
|
||||||
module.exports.check_all = function() {
|
|
||||||
|
var requirements = [
|
||||||
var requirements = [
|
new Requirement('java', 'Java JDK'),
|
||||||
new Requirement('java', 'Java JDK'),
|
new Requirement('androidSdk', 'Android SDK'),
|
||||||
new Requirement('androidSdk', 'Android SDK'),
|
new Requirement('androidTarget', 'Android target'),
|
||||||
new Requirement('androidTarget', 'Android target'),
|
new Requirement('gradle', 'Gradle')
|
||||||
new Requirement('gradle', 'Gradle')
|
];
|
||||||
];
|
|
||||||
|
var checkFns = [
|
||||||
var checkFns = [
|
this.check_java,
|
||||||
this.check_java,
|
this.check_android,
|
||||||
this.check_android,
|
this.check_android_target,
|
||||||
this.check_android_target,
|
this.check_gradle
|
||||||
this.check_gradle
|
];
|
||||||
];
|
|
||||||
|
// Then execute requirement checks one-by-one
|
||||||
// Then execute requirement checks one-by-one
|
return checkFns.reduce(function (promise, checkFn, idx) {
|
||||||
return checkFns.reduce(function (promise, checkFn, idx) {
|
// Update each requirement with results
|
||||||
// Update each requirement with results
|
var requirement = requirements[idx];
|
||||||
var requirement = requirements[idx];
|
return promise.then(checkFn)
|
||||||
return promise.then(checkFn)
|
.then(function (version) {
|
||||||
.then(function (version) {
|
requirement.installed = true;
|
||||||
requirement.installed = true;
|
requirement.metadata.version = version;
|
||||||
requirement.metadata.version = version;
|
}, function (err) {
|
||||||
}, function (err) {
|
requirement.metadata.reason = err instanceof Error ? err.message : err;
|
||||||
requirement.metadata.reason = err instanceof Error ? err.message : err;
|
});
|
||||||
});
|
}, Q())
|
||||||
}, Q())
|
.then(function () {
|
||||||
.then(function () {
|
// When chain is completed, return requirements array to upstream API
|
||||||
// When chain is completed, return requirements array to upstream API
|
return requirements;
|
||||||
return requirements;
|
});
|
||||||
});
|
};
|
||||||
};
|
|
||||||
|
@ -1,331 +1,332 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Licensed to the Apache Software Foundation (ASF) under one
|
Licensed to the Apache Software Foundation (ASF) under one
|
||||||
or more contributor license agreements. See the NOTICE file
|
or more contributor license agreements. See the NOTICE file
|
||||||
distributed with this work for additional information
|
distributed with this work for additional information
|
||||||
regarding copyright ownership. The ASF licenses this file
|
regarding copyright ownership. The ASF licenses this file
|
||||||
to you under the Apache License, Version 2.0 (the
|
to you under the Apache License, Version 2.0 (the
|
||||||
"License"); you may not use this file except in compliance
|
"License"); you may not use this file except in compliance
|
||||||
with the License. You may obtain a copy of the License at
|
with the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing,
|
Unless required by applicable law or agreed to in writing,
|
||||||
software distributed under the License is distributed on an
|
software distributed under the License is distributed on an
|
||||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
KIND, either express or implied. See the License for the
|
KIND, either express or implied. See the License for the
|
||||||
specific language governing permissions and limitations
|
specific language governing permissions and limitations
|
||||||
under the License.
|
under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var shell = require('shelljs'),
|
var shell = require('shelljs'),
|
||||||
Q = require('q'),
|
Q = require('q'),
|
||||||
path = require('path'),
|
path = require('path'),
|
||||||
fs = require('fs'),
|
fs = require('fs'),
|
||||||
check_reqs = require('./check_reqs'),
|
check_reqs = require('./check_reqs'),
|
||||||
ROOT = path.join(__dirname, '..', '..');
|
ROOT = path.join(__dirname, '..', '..');
|
||||||
|
|
||||||
function setShellFatal(value, func) {
|
var MIN_SDK_VERSION = 14;
|
||||||
var oldVal = shell.config.fatal;
|
|
||||||
shell.config.fatal = value;
|
var CordovaError = require('cordova-common').CordovaError;
|
||||||
func();
|
var AndroidManifest = require('../templates/cordova/lib/AndroidManifest');
|
||||||
shell.config.fatal = oldVal;
|
|
||||||
}
|
function setShellFatal(value, func) {
|
||||||
|
var oldVal = shell.config.fatal;
|
||||||
function getFrameworkDir(projectPath, shared) {
|
shell.config.fatal = value;
|
||||||
return shared ? path.join(ROOT, 'framework') : path.join(projectPath, 'CordovaLib');
|
func();
|
||||||
}
|
shell.config.fatal = oldVal;
|
||||||
|
}
|
||||||
function copyJsAndLibrary(projectPath, shared, projectName) {
|
|
||||||
var nestedCordovaLibPath = getFrameworkDir(projectPath, false);
|
function getFrameworkDir(projectPath, shared) {
|
||||||
var srcCordovaJsPath = path.join(ROOT, 'bin', 'templates', 'project', 'assets', 'www', 'cordova.js');
|
return shared ? path.join(ROOT, 'framework') : path.join(projectPath, 'CordovaLib');
|
||||||
shell.cp('-f', srcCordovaJsPath, path.join(projectPath, 'assets', 'www', 'cordova.js'));
|
}
|
||||||
// Don't fail if there are no old jars.
|
|
||||||
setShellFatal(false, function() {
|
function copyJsAndLibrary(projectPath, shared, projectName) {
|
||||||
shell.ls(path.join(projectPath, 'libs', 'cordova-*.jar')).forEach(function(oldJar) {
|
var nestedCordovaLibPath = getFrameworkDir(projectPath, false);
|
||||||
console.log('Deleting ' + oldJar);
|
var srcCordovaJsPath = path.join(ROOT, 'bin', 'templates', 'project', 'assets', 'www', 'cordova.js');
|
||||||
shell.rm('-f', oldJar);
|
shell.cp('-f', srcCordovaJsPath, path.join(projectPath, 'assets', 'www', 'cordova.js'));
|
||||||
});
|
|
||||||
var wasSymlink = true;
|
// Copy the cordova.js file to platforms/<platform>/platform_www/
|
||||||
try {
|
// The www dir is nuked on each prepare so we keep cordova.js in platform_www
|
||||||
// Delete the symlink if it was one.
|
shell.mkdir('-p', path.join(projectPath, 'platform_www'));
|
||||||
fs.unlinkSync(nestedCordovaLibPath);
|
shell.cp('-f', srcCordovaJsPath, path.join(projectPath, 'platform_www'));
|
||||||
} catch (e) {
|
|
||||||
wasSymlink = false;
|
// Copy cordova-js-src directory into platform_www directory.
|
||||||
}
|
// We need these files to build cordova.js if using browserify method.
|
||||||
// Delete old library project if it existed.
|
shell.cp('-rf', path.join(ROOT, 'cordova-js-src'), path.join(projectPath, 'platform_www'));
|
||||||
if (shared) {
|
|
||||||
shell.rm('-rf', nestedCordovaLibPath);
|
// Don't fail if there are no old jars.
|
||||||
} else if (!wasSymlink) {
|
setShellFatal(false, function() {
|
||||||
// Delete only the src, since Eclipse / Android Studio can't handle their project files being deleted.
|
shell.ls(path.join(projectPath, 'libs', 'cordova-*.jar')).forEach(function(oldJar) {
|
||||||
shell.rm('-rf', path.join(nestedCordovaLibPath, 'src'));
|
console.log('Deleting ' + oldJar);
|
||||||
}
|
shell.rm('-f', oldJar);
|
||||||
});
|
});
|
||||||
if (shared) {
|
var wasSymlink = true;
|
||||||
var relativeFrameworkPath = path.relative(projectPath, getFrameworkDir(projectPath, true));
|
try {
|
||||||
fs.symlinkSync(relativeFrameworkPath, nestedCordovaLibPath, 'dir');
|
// Delete the symlink if it was one.
|
||||||
} else {
|
fs.unlinkSync(nestedCordovaLibPath);
|
||||||
shell.mkdir('-p', nestedCordovaLibPath);
|
} catch (e) {
|
||||||
shell.cp('-f', path.join(ROOT, 'framework', 'AndroidManifest.xml'), nestedCordovaLibPath);
|
wasSymlink = false;
|
||||||
shell.cp('-f', path.join(ROOT, 'framework', 'project.properties'), nestedCordovaLibPath);
|
}
|
||||||
shell.cp('-f', path.join(ROOT, 'framework', 'build.gradle'), nestedCordovaLibPath);
|
// Delete old library project if it existed.
|
||||||
shell.cp('-f', path.join(ROOT, 'framework', 'cordova.gradle'), nestedCordovaLibPath);
|
if (shared) {
|
||||||
shell.cp('-r', path.join(ROOT, 'framework', 'src'), nestedCordovaLibPath);
|
shell.rm('-rf', nestedCordovaLibPath);
|
||||||
}
|
} else if (!wasSymlink) {
|
||||||
}
|
// Delete only the src, since Eclipse / Android Studio can't handle their project files being deleted.
|
||||||
|
shell.rm('-rf', path.join(nestedCordovaLibPath, 'src'));
|
||||||
function extractSubProjectPaths(data) {
|
}
|
||||||
var ret = {};
|
});
|
||||||
var r = /^\s*android\.library\.reference\.\d+=(.*)(?:\s|$)/mg;
|
if (shared) {
|
||||||
var m;
|
var relativeFrameworkPath = path.relative(projectPath, getFrameworkDir(projectPath, true));
|
||||||
while ((m = r.exec(data))) {
|
fs.symlinkSync(relativeFrameworkPath, nestedCordovaLibPath, 'dir');
|
||||||
ret[m[1]] = 1;
|
} else {
|
||||||
}
|
shell.mkdir('-p', nestedCordovaLibPath);
|
||||||
return Object.keys(ret);
|
shell.cp('-f', path.join(ROOT, 'framework', 'AndroidManifest.xml'), nestedCordovaLibPath);
|
||||||
}
|
shell.cp('-f', path.join(ROOT, 'framework', 'project.properties'), nestedCordovaLibPath);
|
||||||
|
shell.cp('-f', path.join(ROOT, 'framework', 'build.gradle'), nestedCordovaLibPath);
|
||||||
function writeProjectProperties(projectPath, target_api) {
|
shell.cp('-f', path.join(ROOT, 'framework', 'cordova.gradle'), nestedCordovaLibPath);
|
||||||
var dstPath = path.join(projectPath, 'project.properties');
|
shell.cp('-r', path.join(ROOT, 'framework', 'src'), nestedCordovaLibPath);
|
||||||
var templatePath = path.join(ROOT, 'bin', 'templates', 'project', 'project.properties');
|
}
|
||||||
var srcPath = fs.existsSync(dstPath) ? dstPath : templatePath;
|
}
|
||||||
var data = fs.readFileSync(srcPath, 'utf8');
|
|
||||||
data = data.replace(/^target=.*/m, 'target=' + target_api);
|
function extractSubProjectPaths(data) {
|
||||||
var subProjects = extractSubProjectPaths(data);
|
var ret = {};
|
||||||
subProjects = subProjects.filter(function(p) {
|
var r = /^\s*android\.library\.reference\.\d+=(.*)(?:\s|$)/mg;
|
||||||
return !(/^CordovaLib$/m.exec(p) ||
|
var m;
|
||||||
/[\\\/]cordova-android[\\\/]framework$/m.exec(p) ||
|
while ((m = r.exec(data))) {
|
||||||
/^(\.\.[\\\/])+framework$/m.exec(p)
|
ret[m[1]] = 1;
|
||||||
);
|
}
|
||||||
});
|
return Object.keys(ret);
|
||||||
subProjects.unshift('CordovaLib');
|
}
|
||||||
data = data.replace(/^\s*android\.library\.reference\.\d+=.*\n/mg, '');
|
|
||||||
if (!/\n$/.exec(data)) {
|
function writeProjectProperties(projectPath, target_api) {
|
||||||
data += '\n';
|
var dstPath = path.join(projectPath, 'project.properties');
|
||||||
}
|
var templatePath = path.join(ROOT, 'bin', 'templates', 'project', 'project.properties');
|
||||||
for (var i = 0; i < subProjects.length; ++i) {
|
var srcPath = fs.existsSync(dstPath) ? dstPath : templatePath;
|
||||||
data += 'android.library.reference.' + (i+1) + '=' + subProjects[i] + '\n';
|
|
||||||
}
|
var data = fs.readFileSync(srcPath, 'utf8');
|
||||||
fs.writeFileSync(dstPath, data);
|
data = data.replace(/^target=.*/m, 'target=' + target_api);
|
||||||
}
|
var subProjects = extractSubProjectPaths(data);
|
||||||
|
subProjects = subProjects.filter(function(p) {
|
||||||
function prepBuildFiles(projectPath) {
|
return !(/^CordovaLib$/m.exec(p) ||
|
||||||
var buildModule = require(path.join(path.resolve(projectPath), 'cordova', 'lib', 'build'));
|
/[\\\/]cordova-android[\\\/]framework$/m.exec(p) ||
|
||||||
buildModule.prepBuildFiles();
|
/^(\.\.[\\\/])+framework$/m.exec(p)
|
||||||
}
|
);
|
||||||
|
});
|
||||||
function copyBuildRules(projectPath) {
|
subProjects.unshift('CordovaLib');
|
||||||
var srcDir = path.join(ROOT, 'bin', 'templates', 'project');
|
data = data.replace(/^\s*android\.library\.reference\.\d+=.*\n/mg, '');
|
||||||
|
if (!/\n$/.exec(data)) {
|
||||||
shell.cp('-f', path.join(srcDir, 'build.gradle'), projectPath);
|
data += '\n';
|
||||||
}
|
}
|
||||||
|
for (var i = 0; i < subProjects.length; ++i) {
|
||||||
function copyScripts(projectPath) {
|
data += 'android.library.reference.' + (i+1) + '=' + subProjects[i] + '\n';
|
||||||
var srcScriptsDir = path.join(ROOT, 'bin', 'templates', 'cordova');
|
}
|
||||||
var destScriptsDir = path.join(projectPath, 'cordova');
|
fs.writeFileSync(dstPath, data);
|
||||||
// Delete old scripts directory if this is an update.
|
}
|
||||||
shell.rm('-rf', destScriptsDir);
|
|
||||||
// Copy in the new ones.
|
function prepBuildFiles(projectPath) {
|
||||||
shell.cp('-r', srcScriptsDir, projectPath);
|
var buildModule = require(path.join(path.resolve(projectPath), 'cordova', 'lib', 'build'));
|
||||||
shell.cp('-r', path.join(ROOT, 'bin', 'node_modules'), destScriptsDir);
|
buildModule.prepBuildFiles();
|
||||||
shell.cp(path.join(ROOT, 'bin', 'check_reqs*'), destScriptsDir);
|
}
|
||||||
shell.cp(path.join(ROOT, 'bin', 'lib', 'check_reqs.js'), path.join(projectPath, 'cordova', 'lib', 'check_reqs.js'));
|
|
||||||
shell.cp(path.join(ROOT, 'bin', 'android_sdk_version'), path.join(destScriptsDir, 'android_sdk_version'));
|
function copyBuildRules(projectPath) {
|
||||||
shell.cp(path.join(ROOT, 'bin', 'lib', 'android_sdk_version.js'), path.join(projectPath, 'cordova', 'lib', 'android_sdk_version.js'));
|
var srcDir = path.join(ROOT, 'bin', 'templates', 'project');
|
||||||
}
|
|
||||||
|
shell.cp('-f', path.join(srcDir, 'build.gradle'), projectPath);
|
||||||
/**
|
}
|
||||||
* Test whether a package name is acceptable for use as an android project.
|
|
||||||
* Returns a promise, fulfilled if the package name is acceptable; rejected
|
function copyScripts(projectPath) {
|
||||||
* otherwise.
|
var srcScriptsDir = path.join(ROOT, 'bin', 'templates', 'cordova');
|
||||||
*/
|
var destScriptsDir = path.join(projectPath, 'cordova');
|
||||||
function validatePackageName(package_name) {
|
// Delete old scripts directory if this is an update.
|
||||||
//Make the package conform to Java package types
|
shell.rm('-rf', destScriptsDir);
|
||||||
//http://developer.android.com/guide/topics/manifest/manifest-element.html#package
|
// Copy in the new ones.
|
||||||
//Enforce underscore limitation
|
shell.cp('-r', srcScriptsDir, projectPath);
|
||||||
if (!/^[a-zA-Z][a-zA-Z0-9_]+(\.[a-zA-Z][a-zA-Z0-9_]*)+$/.test(package_name)) {
|
shell.cp('-r', path.join(ROOT, 'node_modules'), destScriptsDir);
|
||||||
return Q.reject('Package name must look like: com.company.Name');
|
shell.cp(path.join(ROOT, 'bin', 'check_reqs*'), destScriptsDir);
|
||||||
}
|
shell.cp(path.join(ROOT, 'bin', 'lib', 'check_reqs.js'), path.join(projectPath, 'cordova', 'lib', 'check_reqs.js'));
|
||||||
|
shell.cp(path.join(ROOT, 'bin', 'android_sdk_version'), path.join(destScriptsDir, 'android_sdk_version'));
|
||||||
//Class is a reserved word
|
shell.cp(path.join(ROOT, 'bin', 'lib', 'android_sdk_version.js'), path.join(projectPath, 'cordova', 'lib', 'android_sdk_version.js'));
|
||||||
if(/\b[Cc]lass\b/.test(package_name)) {
|
}
|
||||||
return Q.reject('class is a reserved word');
|
|
||||||
}
|
/**
|
||||||
|
* Test whether a package name is acceptable for use as an android project.
|
||||||
return Q.resolve();
|
* Returns a promise, fulfilled if the package name is acceptable; rejected
|
||||||
}
|
* otherwise.
|
||||||
|
*/
|
||||||
/**
|
function validatePackageName(package_name) {
|
||||||
* Test whether a project name is acceptable for use as an android class.
|
//Make the package conform to Java package types
|
||||||
* Returns a promise, fulfilled if the project name is acceptable; rejected
|
//http://developer.android.com/guide/topics/manifest/manifest-element.html#package
|
||||||
* otherwise.
|
//Enforce underscore limitation
|
||||||
*/
|
var msg = 'Error validating package name. ';
|
||||||
function validateProjectName(project_name) {
|
if (!/^[a-zA-Z][a-zA-Z0-9_]+(\.[a-zA-Z][a-zA-Z0-9_]*)+$/.test(package_name)) {
|
||||||
//Make sure there's something there
|
return Q.reject(new CordovaError(msg + 'Package name must look like: com.company.Name'));
|
||||||
if (project_name === '') {
|
}
|
||||||
return Q.reject('Project name cannot be empty');
|
|
||||||
}
|
//Class is a reserved word
|
||||||
|
if(/\b[Cc]lass\b/.test(package_name)) {
|
||||||
//Enforce stupid name error
|
return Q.reject(new CordovaError(msg + '"class" is a reserved word'));
|
||||||
if (project_name === 'CordovaActivity') {
|
}
|
||||||
return Q.reject('Project name cannot be CordovaActivity');
|
|
||||||
}
|
return Q.resolve();
|
||||||
|
}
|
||||||
//Classes in Java don't begin with numbers
|
|
||||||
if (/^[0-9]/.test(project_name)) {
|
/**
|
||||||
return Q.reject('Project name must not begin with a number');
|
* Test whether a project name is acceptable for use as an android class.
|
||||||
}
|
* Returns a promise, fulfilled if the project name is acceptable; rejected
|
||||||
|
* otherwise.
|
||||||
return Q.resolve();
|
*/
|
||||||
}
|
function validateProjectName(project_name) {
|
||||||
|
var msg = 'Error validating project name. ';
|
||||||
/**
|
//Make sure there's something there
|
||||||
* $ create [options]
|
if (project_name === '') {
|
||||||
*
|
return Q.reject(new CordovaError(msg + 'Project name cannot be empty'));
|
||||||
* Creates an android application with the given options.
|
}
|
||||||
*
|
|
||||||
* Options:
|
//Enforce stupid name error
|
||||||
*
|
if (project_name === 'CordovaActivity') {
|
||||||
* - `project_path` {String} Path to the new Cordova android project.
|
return Q.reject(new CordovaError(msg + 'Project name cannot be CordovaActivity'));
|
||||||
* - `package_name`{String} Package name, following reverse-domain style convention.
|
}
|
||||||
* - `project_name` {String} Project name.
|
|
||||||
* - `activity_name` {String} Name for the activity
|
//Classes in Java don't begin with numbers
|
||||||
* - 'project_template_dir' {String} Path to project template (override).
|
if (/^[0-9]/.test(project_name)) {
|
||||||
*
|
return Q.reject(new CordovaError(msg + 'Project name must not begin with a number'));
|
||||||
* Returns a promise.
|
}
|
||||||
*/
|
|
||||||
|
return Q.resolve();
|
||||||
exports.createProject = function(project_path, package_name, project_name, activity_name, project_template_dir, use_shared_project, use_cli_template) {
|
}
|
||||||
// Set default values for path, package and name
|
|
||||||
project_path = typeof project_path !== 'undefined' ? project_path : 'CordovaExample';
|
/**
|
||||||
project_path = path.relative(process.cwd(), project_path);
|
* Creates an android application with the given options.
|
||||||
package_name = typeof package_name !== 'undefined' ? package_name : 'my.cordova.project';
|
*
|
||||||
project_name = typeof project_name !== 'undefined' ? project_name : 'CordovaExample';
|
* @param {String} project_path Path to the new Cordova android project.
|
||||||
project_template_dir = typeof project_template_dir !== 'undefined' ?
|
* @param {ConfigParser} config Instance of ConfigParser to retrieve basic
|
||||||
project_template_dir :
|
* project properties.
|
||||||
path.join(ROOT, 'bin', 'templates', 'project');
|
* @param {Object} [options={}] Various options
|
||||||
|
* @param {String} [options.activityName='MainActivity'] Name for the
|
||||||
var package_as_path = package_name.replace(/\./g, path.sep);
|
* activity
|
||||||
var activity_dir = path.join(project_path, 'src', package_as_path);
|
* @param {Boolean} [options.link=false] Specifies whether javascript files
|
||||||
var safe_activity_name = typeof activity_name !== 'undefined' ? activity_name : 'MainActivity';
|
* and CordovaLib framework will be symlinked to created application.
|
||||||
var activity_path = path.join(activity_dir, safe_activity_name + '.java');
|
* @param {String} [options.customTemplate] Path to project template
|
||||||
var target_api = check_reqs.get_target();
|
* (override)
|
||||||
var manifest_path = path.join(project_path, 'AndroidManifest.xml');
|
* @param {EventEmitter} [events] An EventEmitter instance for logging
|
||||||
|
* events
|
||||||
// Check if project already exists
|
*
|
||||||
if(fs.existsSync(project_path)) {
|
* @return {Promise<String>} Directory where application has been created
|
||||||
return Q.reject('Project already exists! Delete and recreate');
|
*/
|
||||||
}
|
exports.create = function(project_path, config, options, events) {
|
||||||
|
|
||||||
//Make the package conform to Java package types
|
options = options || {};
|
||||||
return validatePackageName(package_name)
|
|
||||||
.then(function() {
|
// Set default values for path, package and name
|
||||||
validateProjectName(project_name);
|
project_path = path.relative(process.cwd(), (project_path || 'CordovaExample'));
|
||||||
}).then(function() {
|
// Check if project already exists
|
||||||
// Log the given values for the project
|
if(fs.existsSync(project_path)) {
|
||||||
console.log('Creating Cordova project for the Android platform:');
|
return Q.reject(new CordovaError('Project already exists! Delete and recreate'));
|
||||||
console.log('\tPath: ' + project_path);
|
}
|
||||||
console.log('\tPackage: ' + package_name);
|
|
||||||
console.log('\tName: ' + project_name);
|
var package_name = config.packageName() || 'my.cordova.project';
|
||||||
console.log('\tActivity: ' + safe_activity_name);
|
var project_name = config.name() ?
|
||||||
console.log('\tAndroid target: ' + target_api);
|
config.name().replace(/[^\w.]/g,'_') : 'CordovaExample';
|
||||||
|
|
||||||
console.log('Copying template files...');
|
var safe_activity_name = config.android_activityName() || options.activityName || 'MainActivity';
|
||||||
|
var target_api = check_reqs.get_target();
|
||||||
setShellFatal(true, function() {
|
|
||||||
// copy project template
|
//Make the package conform to Java package types
|
||||||
shell.cp('-r', path.join(project_template_dir, 'assets'), project_path);
|
return validatePackageName(package_name)
|
||||||
shell.cp('-r', path.join(project_template_dir, 'res'), project_path);
|
.then(function() {
|
||||||
shell.cp(path.join(project_template_dir, 'gitignore'), path.join(project_path, '.gitignore'));
|
validateProjectName(project_name);
|
||||||
|
}).then(function() {
|
||||||
// Manually create directories that would be empty within the template (since git doesn't track directories).
|
// Log the given values for the project
|
||||||
shell.mkdir(path.join(project_path, 'libs'));
|
events.emit('log', 'Creating Cordova project for the Android platform:');
|
||||||
|
events.emit('log', '\tPath: ' + project_path);
|
||||||
// copy cordova.js, cordova.jar
|
events.emit('log', '\tPackage: ' + package_name);
|
||||||
copyJsAndLibrary(project_path, use_shared_project, safe_activity_name);
|
events.emit('log', '\tName: ' + project_name);
|
||||||
|
events.emit('log', '\tActivity: ' + safe_activity_name);
|
||||||
// interpolate the activity name and package
|
events.emit('log', '\tAndroid target: ' + target_api);
|
||||||
shell.mkdir('-p', activity_dir);
|
|
||||||
shell.cp('-f', path.join(project_template_dir, 'Activity.java'), activity_path);
|
events.emit('verbose', 'Copying template files...');
|
||||||
shell.sed('-i', /__ACTIVITY__/, safe_activity_name, activity_path);
|
|
||||||
shell.sed('-i', /__NAME__/, project_name, path.join(project_path, 'res', 'values', 'strings.xml'));
|
setShellFatal(true, function() {
|
||||||
shell.sed('-i', /__ID__/, package_name, activity_path);
|
var project_template_dir = options.customTemplate || path.join(ROOT, 'bin', 'templates', 'project');
|
||||||
|
// copy project template
|
||||||
shell.cp('-f', path.join(project_template_dir, 'AndroidManifest.xml'), manifest_path);
|
shell.cp('-r', path.join(project_template_dir, 'assets'), project_path);
|
||||||
shell.sed('-i', /__ACTIVITY__/, safe_activity_name, manifest_path);
|
shell.cp('-r', path.join(project_template_dir, 'res'), project_path);
|
||||||
shell.sed('-i', /__PACKAGE__/, package_name, manifest_path);
|
shell.cp(path.join(project_template_dir, 'gitignore'), path.join(project_path, '.gitignore'));
|
||||||
shell.sed('-i', /__APILEVEL__/, target_api.split('-')[1], manifest_path);
|
|
||||||
copyScripts(project_path);
|
// Manually create directories that would be empty within the template (since git doesn't track directories).
|
||||||
copyBuildRules(project_path);
|
shell.mkdir(path.join(project_path, 'libs'));
|
||||||
});
|
|
||||||
// Link it to local android install.
|
// copy cordova.js, cordova.jar
|
||||||
writeProjectProperties(project_path, target_api);
|
copyJsAndLibrary(project_path, options.link, safe_activity_name);
|
||||||
prepBuildFiles(project_path);
|
|
||||||
console.log(generateDoneMessage('create', use_shared_project));
|
// interpolate the activity name and package
|
||||||
});
|
var packagePath = package_name.replace(/\./g, path.sep);
|
||||||
};
|
var activity_dir = path.join(project_path, 'src', packagePath);
|
||||||
|
var activity_path = path.join(activity_dir, safe_activity_name + '.java');
|
||||||
function generateDoneMessage(type, link) {
|
shell.mkdir('-p', activity_dir);
|
||||||
var pkg = require('../../package');
|
shell.cp('-f', path.join(project_template_dir, 'Activity.java'), activity_path);
|
||||||
var msg = 'Android project ' + (type == 'update' ? 'updated ' : 'created ') + 'with ' + pkg.name + '@' + pkg.version;
|
shell.sed('-i', /__ACTIVITY__/, safe_activity_name, activity_path);
|
||||||
if (link) {
|
shell.sed('-i', /__NAME__/, project_name, path.join(project_path, 'res', 'values', 'strings.xml'));
|
||||||
msg += ' and has a linked CordovaLib';
|
shell.sed('-i', /__ID__/, package_name, activity_path);
|
||||||
}
|
|
||||||
return msg;
|
var manifest = new AndroidManifest(path.join(project_template_dir, 'AndroidManifest.xml'));
|
||||||
}
|
manifest.setPackageId(package_name)
|
||||||
|
.setTargetSdkVersion(target_api.split('-')[1])
|
||||||
// Attribute removed in Cordova 4.4 (CB-5447).
|
.getActivity().setName(safe_activity_name);
|
||||||
function removeDebuggableFromManifest(projectPath) {
|
|
||||||
var manifestPath = path.join(projectPath, 'AndroidManifest.xml');
|
var manifest_path = path.join(project_path, 'AndroidManifest.xml');
|
||||||
shell.sed('-i', /\s*android:debuggable="true"/, '', manifestPath);
|
manifest.write(manifest_path);
|
||||||
}
|
|
||||||
|
copyScripts(project_path);
|
||||||
function extractProjectNameFromManifest(projectPath) {
|
copyBuildRules(project_path);
|
||||||
var manifestPath = path.join(projectPath, 'AndroidManifest.xml');
|
});
|
||||||
var manifestData = fs.readFileSync(manifestPath, 'utf8');
|
// Link it to local android install.
|
||||||
var m = /<activity[\s\S]*?android:name\s*=\s*"(.*?)"/i.exec(manifestData);
|
writeProjectProperties(project_path, target_api);
|
||||||
if (!m) {
|
prepBuildFiles(project_path);
|
||||||
throw new Error('Could not find activity name in ' + manifestPath);
|
events.emit('log', generateDoneMessage('create', options.link));
|
||||||
}
|
}).thenResolve(project_path);
|
||||||
return m[1];
|
};
|
||||||
}
|
|
||||||
|
function generateDoneMessage(type, link) {
|
||||||
// Cordova-android updates sometimes drop support for older versions. Need to update minSDK in existing projects.
|
var pkg = require('../../package');
|
||||||
function updateMinSDKInManifest(projectPath) {
|
var msg = 'Android project ' + (type == 'update' ? 'updated ' : 'created ') + 'with ' + pkg.name + '@' + pkg.version;
|
||||||
var manifestPath = path.join(projectPath, 'AndroidManifest.xml');
|
if (link) {
|
||||||
var manifestData = fs.readFileSync(manifestPath, 'utf8');
|
msg += ' and has a linked CordovaLib';
|
||||||
var minSDKVersion = 14;
|
}
|
||||||
|
return msg;
|
||||||
//grab minSdkVersion from Android.
|
}
|
||||||
var m = /android:minSdkVersion\s*=\s*"(.*?)"/i.exec(manifestData);
|
|
||||||
if (!m) {
|
// Returns a promise.
|
||||||
throw new Error('Could not find minSDKVersion in ' + manifestPath);
|
exports.update = function(projectPath, options, events) {
|
||||||
}
|
options = options || {};
|
||||||
//if minSDKVersion in Android.manifest is less than our current min, replace it
|
|
||||||
if(Number(m[1]) < minSDKVersion) {
|
return Q()
|
||||||
console.log('Updating minSdkVersion from ' + m[1] + ' to ' + minSDKVersion + ' in AndroidManifest.xml');
|
.then(function() {
|
||||||
shell.sed('-i', /android:minSdkVersion\s*=\s*"(.*?)"/, 'android:minSdkVersion="'+minSDKVersion+'"', manifestPath);
|
|
||||||
}
|
var manifest = new AndroidManifest(path.join(projectPath, 'AndroidManifest.xml'));
|
||||||
}
|
|
||||||
|
if (Number(manifest.getMinSdkVersion()) < MIN_SDK_VERSION) {
|
||||||
// Returns a promise.
|
events.emit('verbose', 'Updating minSdkVersion to ' + MIN_SDK_VERSION + ' in AndroidManifest.xml');
|
||||||
exports.updateProject = function(projectPath, shared) {
|
manifest.setMinSDKVersion(MIN_SDK_VERSION);
|
||||||
return Q()
|
}
|
||||||
.then(function() {
|
|
||||||
var projectName = extractProjectNameFromManifest(projectPath);
|
manifest.setDebuggable(false).write();
|
||||||
var target_api = check_reqs.get_target();
|
|
||||||
updateMinSDKInManifest(projectPath);
|
var projectName = manifest.getActivity().getName();
|
||||||
copyJsAndLibrary(projectPath, shared, projectName);
|
var target_api = check_reqs.get_target();
|
||||||
copyScripts(projectPath);
|
|
||||||
copyBuildRules(projectPath);
|
copyJsAndLibrary(projectPath, options.link, projectName);
|
||||||
removeDebuggableFromManifest(projectPath);
|
copyScripts(projectPath);
|
||||||
writeProjectProperties(projectPath, target_api);
|
copyBuildRules(projectPath);
|
||||||
prepBuildFiles(projectPath);
|
writeProjectProperties(projectPath, target_api);
|
||||||
console.log(generateDoneMessage('update', shared));
|
prepBuildFiles(projectPath);
|
||||||
});
|
events.emit('log', generateDoneMessage('update', options.link));
|
||||||
};
|
}).thenResolve(projectPath);
|
||||||
|
};
|
||||||
|
|
||||||
// For testing
|
|
||||||
exports.validatePackageName = validatePackageName;
|
// For testing
|
||||||
exports.validateProjectName = validateProjectName;
|
exports.validatePackageName = validatePackageName;
|
||||||
|
exports.validateProjectName = validateProjectName;
|
||||||
|
@ -1,32 +0,0 @@
|
|||||||
/*
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.getArgs = function(argv) {
|
|
||||||
var ret = {};
|
|
||||||
var posArgs = [];
|
|
||||||
for (var i = 2, arg; (arg = argv[i] || i < argv.length); ++i) {
|
|
||||||
if (/^--/.exec(arg)) {
|
|
||||||
ret[arg] = true;
|
|
||||||
} else {
|
|
||||||
posArgs.push(arg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ret._ = posArgs;
|
|
||||||
return ret;
|
|
||||||
};
|
|
1
bin/node_modules/.bin/shjs
generated
vendored
1
bin/node_modules/.bin/shjs
generated
vendored
@ -1 +0,0 @@
|
|||||||
../shelljs/bin/shjs
|
|
23
bin/node_modules/nopt/node_modules/abbrev/LICENSE
generated
vendored
23
bin/node_modules/nopt/node_modules/abbrev/LICENSE
generated
vendored
@ -1,23 +0,0 @@
|
|||||||
Copyright 2009, 2010, 2011 Isaac Z. Schlueter.
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
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.
|
|
31
bin/node_modules/nopt/node_modules/abbrev/package.json
generated
vendored
31
bin/node_modules/nopt/node_modules/abbrev/package.json
generated
vendored
@ -1,31 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "abbrev",
|
|
||||||
"version": "1.0.5",
|
|
||||||
"description": "Like ruby's abbrev module, but in js",
|
|
||||||
"author": {
|
|
||||||
"name": "Isaac Z. Schlueter",
|
|
||||||
"email": "i@izs.me"
|
|
||||||
},
|
|
||||||
"main": "abbrev.js",
|
|
||||||
"scripts": {
|
|
||||||
"test": "node test.js"
|
|
||||||
},
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "http://github.com/isaacs/abbrev-js"
|
|
||||||
},
|
|
||||||
"license": {
|
|
||||||
"type": "MIT",
|
|
||||||
"url": "https://github.com/isaacs/abbrev-js/raw/master/LICENSE"
|
|
||||||
},
|
|
||||||
"readme": "# abbrev-js\n\nJust like [ruby's Abbrev](http://apidock.com/ruby/Abbrev).\n\nUsage:\n\n var abbrev = require(\"abbrev\");\n abbrev(\"foo\", \"fool\", \"folding\", \"flop\");\n \n // returns:\n { fl: 'flop'\n , flo: 'flop'\n , flop: 'flop'\n , fol: 'folding'\n , fold: 'folding'\n , foldi: 'folding'\n , foldin: 'folding'\n , folding: 'folding'\n , foo: 'foo'\n , fool: 'fool'\n }\n\nThis is handy for command-line scripts, or other cases where you want to be able to accept shorthands.\n",
|
|
||||||
"readmeFilename": "README.md",
|
|
||||||
"bugs": {
|
|
||||||
"url": "https://github.com/isaacs/abbrev-js/issues"
|
|
||||||
},
|
|
||||||
"homepage": "https://github.com/isaacs/abbrev-js",
|
|
||||||
"_id": "abbrev@1.0.5",
|
|
||||||
"_shasum": "5d8257bd9ebe435e698b2fa431afde4fe7b10b03",
|
|
||||||
"_from": "abbrev@1",
|
|
||||||
"_resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.5.tgz"
|
|
||||||
}
|
|
41
bin/node_modules/nopt/package.json
generated
vendored
41
bin/node_modules/nopt/package.json
generated
vendored
File diff suppressed because one or more lines are too long
40
bin/node_modules/q/CONTRIBUTING.md
generated
vendored
40
bin/node_modules/q/CONTRIBUTING.md
generated
vendored
@ -1,40 +0,0 @@
|
|||||||
|
|
||||||
For pull requests:
|
|
||||||
|
|
||||||
- Be consistent with prevalent style and design decisions.
|
|
||||||
- Add a Jasmine spec to `specs/q-spec.js`.
|
|
||||||
- Use `npm test` to avoid regressions.
|
|
||||||
- Run tests in `q-spec/run.html` in as many supported browsers as you
|
|
||||||
can find the will to deal with.
|
|
||||||
- Do not build minified versions; we do this each release.
|
|
||||||
- If you would be so kind, add a note to `CHANGES.md` in an
|
|
||||||
appropriate section:
|
|
||||||
|
|
||||||
- `Next Major Version` if it introduces backward incompatibilities
|
|
||||||
to code in the wild using documented features.
|
|
||||||
- `Next Minor Version` if it adds a new feature.
|
|
||||||
- `Next Patch Version` if it fixes a bug.
|
|
||||||
|
|
||||||
For releases:
|
|
||||||
|
|
||||||
- Run `npm test`.
|
|
||||||
- Run tests in `q-spec/run.html` in a representative sample of every
|
|
||||||
browser under the sun.
|
|
||||||
- Run `npm run cover` and make sure you're happy with the results.
|
|
||||||
- Run `npm run minify` and be sure to commit the resulting `q.min.js`.
|
|
||||||
- Note the Gzipped size output by the previous command, and update
|
|
||||||
`README.md` if it has changed to 1 significant digit.
|
|
||||||
- Stash any local changes.
|
|
||||||
- Update `CHANGES.md` to reflect all changes in the differences
|
|
||||||
between `HEAD` and the previous tagged version. Give credit where
|
|
||||||
credit is due.
|
|
||||||
- Update `README.md` to address all new, non-experimental features.
|
|
||||||
- Update the API reference on the Wiki to reflect all non-experimental
|
|
||||||
features.
|
|
||||||
- Use `npm version major|minor|patch` to update `package.json`,
|
|
||||||
commit, and tag the new version.
|
|
||||||
- Use `npm publish` to send up a new release.
|
|
||||||
- Send an email to the q-continuum mailing list announcing the new
|
|
||||||
release and the notes from the change log. This helps folks
|
|
||||||
maintaining other package ecosystems.
|
|
||||||
|
|
71
bin/node_modules/q/benchmark/compare-with-callbacks.js
generated
vendored
71
bin/node_modules/q/benchmark/compare-with-callbacks.js
generated
vendored
@ -1,71 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
var Q = require("../q");
|
|
||||||
var fs = require("fs");
|
|
||||||
|
|
||||||
suite("A single simple async operation", function () {
|
|
||||||
bench("with an immediately-fulfilled promise", function (done) {
|
|
||||||
Q().then(done);
|
|
||||||
});
|
|
||||||
|
|
||||||
bench("with direct setImmediate usage", function (done) {
|
|
||||||
setImmediate(done);
|
|
||||||
});
|
|
||||||
|
|
||||||
bench("with direct setTimeout(…, 0)", function (done) {
|
|
||||||
setTimeout(done, 0);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
suite("A fs.readFile", function () {
|
|
||||||
var denodeified = Q.denodeify(fs.readFile);
|
|
||||||
|
|
||||||
set("iterations", 1000);
|
|
||||||
set("delay", 1000);
|
|
||||||
|
|
||||||
bench("directly, with callbacks", function (done) {
|
|
||||||
fs.readFile(__filename, done);
|
|
||||||
});
|
|
||||||
|
|
||||||
bench("with Q.nfcall", function (done) {
|
|
||||||
Q.nfcall(fs.readFile, __filename).then(done);
|
|
||||||
});
|
|
||||||
|
|
||||||
bench("with a Q.denodeify'ed version", function (done) {
|
|
||||||
denodeified(__filename).then(done);
|
|
||||||
});
|
|
||||||
|
|
||||||
bench("with manual usage of deferred.makeNodeResolver", function (done) {
|
|
||||||
var deferred = Q.defer();
|
|
||||||
fs.readFile(__filename, deferred.makeNodeResolver());
|
|
||||||
deferred.promise.then(done);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
suite("1000 operations in parallel", function () {
|
|
||||||
function makeCounter(desiredCount, ultimateCallback) {
|
|
||||||
var soFar = 0;
|
|
||||||
return function () {
|
|
||||||
if (++soFar === desiredCount) {
|
|
||||||
ultimateCallback();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
var numberOfOps = 1000;
|
|
||||||
|
|
||||||
bench("with immediately-fulfilled promises", function (done) {
|
|
||||||
var counter = makeCounter(numberOfOps, done);
|
|
||||||
|
|
||||||
for (var i = 0; i < numberOfOps; ++i) {
|
|
||||||
Q().then(counter);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
bench("with direct setImmediate usage", function (done) {
|
|
||||||
var counter = makeCounter(numberOfOps, done);
|
|
||||||
|
|
||||||
for (var i = 0; i < numberOfOps; ++i) {
|
|
||||||
setImmediate(counter);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
36
bin/node_modules/q/benchmark/scenarios.js
generated
vendored
36
bin/node_modules/q/benchmark/scenarios.js
generated
vendored
@ -1,36 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
var Q = require("../q");
|
|
||||||
|
|
||||||
suite("Chaining", function () {
|
|
||||||
var numberToChain = 1000;
|
|
||||||
|
|
||||||
bench("Chaining many already-fulfilled promises together", function (done) {
|
|
||||||
var currentPromise = Q();
|
|
||||||
for (var i = 0; i < numberToChain; ++i) {
|
|
||||||
currentPromise = currentPromise.then(function () {
|
|
||||||
return Q();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
currentPromise.then(done);
|
|
||||||
});
|
|
||||||
|
|
||||||
bench("Chaining and then fulfilling the end of the chain", function (done) {
|
|
||||||
var deferred = Q.defer();
|
|
||||||
|
|
||||||
var currentPromise = deferred.promise;
|
|
||||||
for (var i = 0; i < numberToChain; ++i) {
|
|
||||||
(function () {
|
|
||||||
var promiseToReturn = currentPromise;
|
|
||||||
currentPromise = Q().then(function () {
|
|
||||||
return promiseToReturn;
|
|
||||||
});
|
|
||||||
}());
|
|
||||||
}
|
|
||||||
|
|
||||||
currentPromise.then(done);
|
|
||||||
|
|
||||||
deferred.resolve();
|
|
||||||
});
|
|
||||||
});
|
|
93
bin/node_modules/q/package.json
generated
vendored
93
bin/node_modules/q/package.json
generated
vendored
File diff suppressed because one or more lines are too long
48
bin/node_modules/shelljs/package.json
generated
vendored
48
bin/node_modules/shelljs/package.json
generated
vendored
File diff suppressed because one or more lines are too long
23
bin/node_modules/which/LICENSE
generated
vendored
23
bin/node_modules/which/LICENSE
generated
vendored
@ -1,23 +0,0 @@
|
|||||||
Copyright 2009, 2010, 2011 Isaac Z. Schlueter.
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
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.
|
|
5
bin/node_modules/which/README.md
generated
vendored
5
bin/node_modules/which/README.md
generated
vendored
@ -1,5 +0,0 @@
|
|||||||
The "which" util from npm's guts.
|
|
||||||
|
|
||||||
Finds the first instance of a specified executable in the PATH
|
|
||||||
environment variable. Does not cache the results, so `hash -r` is not
|
|
||||||
needed when the PATH changes.
|
|
14
bin/node_modules/which/bin/which
generated
vendored
14
bin/node_modules/which/bin/which
generated
vendored
@ -1,14 +0,0 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
var which = require("../")
|
|
||||||
if (process.argv.length < 3) {
|
|
||||||
console.error("Usage: which <thing>")
|
|
||||||
process.exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
which(process.argv[2], function (er, thing) {
|
|
||||||
if (er) {
|
|
||||||
console.error(er.message)
|
|
||||||
process.exit(er.errno || 127)
|
|
||||||
}
|
|
||||||
console.log(thing)
|
|
||||||
})
|
|
31
bin/node_modules/which/package.json
generated
vendored
31
bin/node_modules/which/package.json
generated
vendored
@ -1,31 +0,0 @@
|
|||||||
{
|
|
||||||
"author": {
|
|
||||||
"name": "Isaac Z. Schlueter",
|
|
||||||
"email": "i@izs.me",
|
|
||||||
"url": "http://blog.izs.me"
|
|
||||||
},
|
|
||||||
"name": "which",
|
|
||||||
"description": "Like which(1) unix command. Find the first instance of an executable in the PATH.",
|
|
||||||
"version": "1.0.5",
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "git://github.com/isaacs/node-which.git"
|
|
||||||
},
|
|
||||||
"main": "which.js",
|
|
||||||
"bin": {
|
|
||||||
"which": "./bin/which"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "*"
|
|
||||||
},
|
|
||||||
"dependencies": {},
|
|
||||||
"devDependencies": {},
|
|
||||||
"readme": "The \"which\" util from npm's guts.\n\nFinds the first instance of a specified executable in the PATH\nenvironment variable. Does not cache the results, so `hash -r` is not\nneeded when the PATH changes.\n",
|
|
||||||
"readmeFilename": "README.md",
|
|
||||||
"bugs": {
|
|
||||||
"url": "https://github.com/isaacs/node-which/issues"
|
|
||||||
},
|
|
||||||
"homepage": "https://github.com/isaacs/node-which",
|
|
||||||
"_id": "which@1.0.5",
|
|
||||||
"_from": "which@"
|
|
||||||
}
|
|
104
bin/node_modules/which/which.js
generated
vendored
104
bin/node_modules/which/which.js
generated
vendored
@ -1,104 +0,0 @@
|
|||||||
module.exports = which
|
|
||||||
which.sync = whichSync
|
|
||||||
|
|
||||||
var path = require("path")
|
|
||||||
, fs
|
|
||||||
, COLON = process.platform === "win32" ? ";" : ":"
|
|
||||||
, isExe
|
|
||||||
|
|
||||||
try {
|
|
||||||
fs = require("graceful-fs")
|
|
||||||
} catch (ex) {
|
|
||||||
fs = require("fs")
|
|
||||||
}
|
|
||||||
|
|
||||||
if (process.platform == "win32") {
|
|
||||||
// On windows, there is no good way to check that a file is executable
|
|
||||||
isExe = function isExe () { return true }
|
|
||||||
} else {
|
|
||||||
isExe = function isExe (mod, uid, gid) {
|
|
||||||
//console.error(mod, uid, gid);
|
|
||||||
//console.error("isExe?", (mod & 0111).toString(8))
|
|
||||||
var ret = (mod & 0001)
|
|
||||||
|| (mod & 0010) && process.getgid && gid === process.getgid()
|
|
||||||
|| (mod & 0100) && process.getuid && uid === process.getuid()
|
|
||||||
//console.error("isExe?", ret)
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function which (cmd, cb) {
|
|
||||||
if (isAbsolute(cmd)) return cb(null, cmd)
|
|
||||||
var pathEnv = (process.env.PATH || "").split(COLON)
|
|
||||||
, pathExt = [""]
|
|
||||||
if (process.platform === "win32") {
|
|
||||||
pathEnv.push(process.cwd())
|
|
||||||
pathExt = (process.env.PATHEXT || ".EXE").split(COLON)
|
|
||||||
if (cmd.indexOf(".") !== -1) pathExt.unshift("")
|
|
||||||
}
|
|
||||||
//console.error("pathEnv", pathEnv)
|
|
||||||
;(function F (i, l) {
|
|
||||||
if (i === l) return cb(new Error("not found: "+cmd))
|
|
||||||
var p = path.resolve(pathEnv[i], cmd)
|
|
||||||
;(function E (ii, ll) {
|
|
||||||
if (ii === ll) return F(i + 1, l)
|
|
||||||
var ext = pathExt[ii]
|
|
||||||
//console.error(p + ext)
|
|
||||||
fs.stat(p + ext, function (er, stat) {
|
|
||||||
if (!er &&
|
|
||||||
stat &&
|
|
||||||
stat.isFile() &&
|
|
||||||
isExe(stat.mode, stat.uid, stat.gid)) {
|
|
||||||
//console.error("yes, exe!", p + ext)
|
|
||||||
return cb(null, p + ext)
|
|
||||||
}
|
|
||||||
return E(ii + 1, ll)
|
|
||||||
})
|
|
||||||
})(0, pathExt.length)
|
|
||||||
})(0, pathEnv.length)
|
|
||||||
}
|
|
||||||
|
|
||||||
function whichSync (cmd) {
|
|
||||||
if (isAbsolute(cmd)) return cmd
|
|
||||||
var pathEnv = (process.env.PATH || "").split(COLON)
|
|
||||||
, pathExt = [""]
|
|
||||||
if (process.platform === "win32") {
|
|
||||||
pathEnv.push(process.cwd())
|
|
||||||
pathExt = (process.env.PATHEXT || ".EXE").split(COLON)
|
|
||||||
if (cmd.indexOf(".") !== -1) pathExt.unshift("")
|
|
||||||
}
|
|
||||||
for (var i = 0, l = pathEnv.length; i < l; i ++) {
|
|
||||||
var p = path.join(pathEnv[i], cmd)
|
|
||||||
for (var j = 0, ll = pathExt.length; j < ll; j ++) {
|
|
||||||
var cur = p + pathExt[j]
|
|
||||||
var stat
|
|
||||||
try { stat = fs.statSync(cur) } catch (ex) {}
|
|
||||||
if (stat &&
|
|
||||||
stat.isFile() &&
|
|
||||||
isExe(stat.mode, stat.uid, stat.gid)) return cur
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw new Error("not found: "+cmd)
|
|
||||||
}
|
|
||||||
|
|
||||||
var isAbsolute = process.platform === "win32" ? absWin : absUnix
|
|
||||||
|
|
||||||
function absWin (p) {
|
|
||||||
if (absUnix(p)) return true
|
|
||||||
// pull off the device/UNC bit from a windows path.
|
|
||||||
// from node's lib/path.js
|
|
||||||
var splitDeviceRe =
|
|
||||||
/^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/][^\\\/]+)?([\\\/])?/
|
|
||||||
, result = splitDeviceRe.exec(p)
|
|
||||||
, device = result[1] || ''
|
|
||||||
, isUnc = device && device.charAt(1) !== ':'
|
|
||||||
, isAbsolute = !!result[2] || isUnc // UNC paths are always absolute
|
|
||||||
|
|
||||||
return isAbsolute
|
|
||||||
}
|
|
||||||
|
|
||||||
function absUnix (p) {
|
|
||||||
return p.charAt(0) === "/" || p === ""
|
|
||||||
}
|
|
10
bin/templates/cordova/.jshintrc
Normal file
10
bin/templates/cordova/.jshintrc
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"node": true
|
||||||
|
, "bitwise": true
|
||||||
|
, "undef": true
|
||||||
|
, "trailing": true
|
||||||
|
, "quotmark": true
|
||||||
|
, "indent": 4
|
||||||
|
, "unused": "vars"
|
||||||
|
, "latedef": "nofunc"
|
||||||
|
}
|
492
bin/templates/cordova/Api.js
vendored
Normal file
492
bin/templates/cordova/Api.js
vendored
Normal file
@ -0,0 +1,492 @@
|
|||||||
|
/**
|
||||||
|
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 Q = require('q');
|
||||||
|
var fs = require('fs');
|
||||||
|
var path = require('path');
|
||||||
|
var shell = require('shelljs');
|
||||||
|
|
||||||
|
var CordovaError = require('cordova-common').CordovaError;
|
||||||
|
var PlatformJson = require('cordova-common').PlatformJson;
|
||||||
|
var ActionStack = require('cordova-common').ActionStack;
|
||||||
|
var AndroidProject = require('./lib/AndroidProject');
|
||||||
|
var PlatformMunger = require('cordova-common').ConfigChanges.PlatformMunger;
|
||||||
|
var PluginInfoProvider = require('cordova-common').PluginInfoProvider;
|
||||||
|
|
||||||
|
var ConsoleLogger = require('./lib/ConsoleLogger');
|
||||||
|
var pluginHandlers = require('./lib/pluginHandlers');
|
||||||
|
|
||||||
|
var PLATFORM = 'android';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class, that acts as abstraction over particular platform. Encapsulates the
|
||||||
|
* platform's properties and methods.
|
||||||
|
*
|
||||||
|
* Platform that implements own PlatformApi instance _should implement all
|
||||||
|
* prototype methods_ of this class to be fully compatible with cordova-lib.
|
||||||
|
*
|
||||||
|
* The PlatformApi instance also should define the following field:
|
||||||
|
*
|
||||||
|
* * platform: String that defines a platform name.
|
||||||
|
*/
|
||||||
|
function Api(platform, platformRootDir, events) {
|
||||||
|
this.platform = PLATFORM;
|
||||||
|
this.root = path.resolve(__dirname, '..');
|
||||||
|
this.events = events || ConsoleLogger.get();
|
||||||
|
// NOTE: trick to share one EventEmitter instance across all js code
|
||||||
|
require('cordova-common').events = this.events;
|
||||||
|
|
||||||
|
this._platformJson = PlatformJson.load(this.root, platform);
|
||||||
|
this._pluginInfoProvider = new PluginInfoProvider();
|
||||||
|
this._munger = new PlatformMunger(this.platform, this.root, this._platformJson, this._pluginInfoProvider);
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
this.locations = {
|
||||||
|
root: self.root,
|
||||||
|
www: path.join(self.root, 'assets/www'),
|
||||||
|
platformWww: path.join(self.root, 'platform_www'),
|
||||||
|
configXml: path.join(self.root, 'res/xml/config.xml'),
|
||||||
|
defaultConfigXml: path.join(self.root, 'cordova/defaults.xml'),
|
||||||
|
strings: path.join(self.root, 'res/values/strings.xml'),
|
||||||
|
manifest: path.join(self.root, 'AndroidManifest.xml'),
|
||||||
|
// NOTE: Due to platformApi spec we need to return relative paths here
|
||||||
|
cordovaJs: 'bin/templates/project/assets/www/cordova.js',
|
||||||
|
cordovaJsSrc: 'cordova-js-src'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Installs platform to specified directory and creates a platform project.
|
||||||
|
*
|
||||||
|
* @param {String} destination Destination directory, where insatll platform to
|
||||||
|
* @param {ConfigParser} [config] ConfgiParser instance, used to retrieve
|
||||||
|
* project creation options, such as package id and project name.
|
||||||
|
* @param {Object} [options] An options object. The most common options are:
|
||||||
|
* @param {String} [options.customTemplate] A path to custom template, that
|
||||||
|
* should override the default one from platform.
|
||||||
|
* @param {Boolean} [options.link] Flag that indicates that platform's
|
||||||
|
* sources will be linked to installed platform instead of copying.
|
||||||
|
* @param {EventEmitter} [events] An EventEmitter instance that will be used for
|
||||||
|
* logging purposes. If no EventEmitter provided, all events will be logged to
|
||||||
|
* console
|
||||||
|
*
|
||||||
|
* @return {Promise<PlatformApi>} Promise either fulfilled with PlatformApi
|
||||||
|
* instance or rejected with CordovaError.
|
||||||
|
*/
|
||||||
|
Api.createPlatform = function (destination, config, options, events) {
|
||||||
|
return require('../../lib/create')
|
||||||
|
.create(destination, config, options, events || ConsoleLogger.get())
|
||||||
|
.then(function (destination) {
|
||||||
|
var PlatformApi = require(path.resolve(destination, 'cordova/Api'));
|
||||||
|
return new PlatformApi(PLATFORM, destination, events);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates already installed platform.
|
||||||
|
*
|
||||||
|
* @param {String} destination Destination directory, where platform installed
|
||||||
|
* @param {Object} [options] An options object. The most common options are:
|
||||||
|
* @param {String} [options.customTemplate] A path to custom template, that
|
||||||
|
* should override the default one from platform.
|
||||||
|
* @param {Boolean} [options.link] Flag that indicates that platform's
|
||||||
|
* sources will be linked to installed platform instead of copying.
|
||||||
|
* @param {EventEmitter} [events] An EventEmitter instance that will be used for
|
||||||
|
* logging purposes. If no EventEmitter provided, all events will be logged to
|
||||||
|
* console
|
||||||
|
*
|
||||||
|
* @return {Promise<PlatformApi>} Promise either fulfilled with PlatformApi
|
||||||
|
* instance or rejected with CordovaError.
|
||||||
|
*/
|
||||||
|
Api.updatePlatform = function (destination, options, events) {
|
||||||
|
return require('../../lib/create')
|
||||||
|
.update(destination, options, events || ConsoleLogger.get())
|
||||||
|
.then(function (destination) {
|
||||||
|
var PlatformApi = require(path.resolve(destination, 'cordova/Api'));
|
||||||
|
return new PlatformApi('android', destination, events);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a CordovaPlatform object, that represents the platform structure.
|
||||||
|
*
|
||||||
|
* @return {CordovaPlatform} A structure that contains the description of
|
||||||
|
* platform's file structure and other properties of platform.
|
||||||
|
*/
|
||||||
|
Api.prototype.getPlatformInfo = function () {
|
||||||
|
var result = {};
|
||||||
|
result.locations = this.locations;
|
||||||
|
result.root = this.root;
|
||||||
|
result.name = this.platform;
|
||||||
|
result.version = require('./version');
|
||||||
|
result.projectConfig = this._config;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates installed platform with provided www assets and new app
|
||||||
|
* configuration. This method is required for CLI workflow and will be called
|
||||||
|
* each time before build, so the changes, made to app configuration and www
|
||||||
|
* code, will be applied to platform.
|
||||||
|
*
|
||||||
|
* @param {CordovaProject} cordovaProject A CordovaProject instance, that defines a
|
||||||
|
* project structure and configuration, that should be applied to platform
|
||||||
|
* (contains project's www location and ConfigParser instance for project's
|
||||||
|
* config).
|
||||||
|
*
|
||||||
|
* @return {Promise} Return a promise either fulfilled, or rejected with
|
||||||
|
* CordovaError instance.
|
||||||
|
*/
|
||||||
|
Api.prototype.prepare = function (cordovaProject) {
|
||||||
|
return require('./lib/prepare').prepare.call(this, cordovaProject);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Installs a new plugin into platform. This method only copies non-www files
|
||||||
|
* (sources, libs, etc.) to platform. It also doesn't resolves the
|
||||||
|
* dependencies of plugin. Both of handling of www files, such as assets and
|
||||||
|
* js-files and resolving dependencies are the responsibility of caller.
|
||||||
|
*
|
||||||
|
* @param {PluginInfo} plugin A PluginInfo instance that represents plugin
|
||||||
|
* that will be installed.
|
||||||
|
* @param {Object} installOptions An options object. Possible options below:
|
||||||
|
* @param {Boolean} installOptions.link: Flag that specifies that plugin
|
||||||
|
* sources will be symlinked to app's directory instead of copying (if
|
||||||
|
* possible).
|
||||||
|
* @param {Object} installOptions.variables An object that represents
|
||||||
|
* variables that will be used to install plugin. See more details on plugin
|
||||||
|
* variables in documentation:
|
||||||
|
* https://cordova.apache.org/docs/en/4.0.0/plugin_ref_spec.md.html
|
||||||
|
*
|
||||||
|
* @return {Promise} Return a promise either fulfilled, or rejected with
|
||||||
|
* CordovaError instance.
|
||||||
|
*/
|
||||||
|
Api.prototype.addPlugin = function (plugin, installOptions) {
|
||||||
|
|
||||||
|
if (!plugin || plugin.constructor.name !== 'PluginInfo')
|
||||||
|
return Q.reject(new CordovaError('The parameter is incorrect. The first parameter to addPlugin should be a PluginInfo instance'));
|
||||||
|
|
||||||
|
installOptions = installOptions || {};
|
||||||
|
installOptions.variables = installOptions.variables || {};
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
var actions = new ActionStack();
|
||||||
|
var project = AndroidProject.getProjectFile(this.root);
|
||||||
|
|
||||||
|
// gather all files needs to be handled during install
|
||||||
|
plugin.getFilesAndFrameworks(this.platform)
|
||||||
|
.concat(plugin.getAssets(this.platform))
|
||||||
|
.concat(plugin.getJsModules(this.platform))
|
||||||
|
.forEach(function(item) {
|
||||||
|
actions.push(actions.createAction(
|
||||||
|
pluginHandlers.getInstaller(item.itemType), [item, plugin, project, installOptions],
|
||||||
|
pluginHandlers.getUninstaller(item.itemType), [item, plugin, project, installOptions]));
|
||||||
|
});
|
||||||
|
|
||||||
|
// run through the action stack
|
||||||
|
return actions.process(this.platform)
|
||||||
|
.then(function () {
|
||||||
|
if (project) {
|
||||||
|
project.write();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add PACKAGE_NAME variable into vars
|
||||||
|
if (!installOptions.variables.PACKAGE_NAME) {
|
||||||
|
installOptions.variables.PACKAGE_NAME = project.getPackageName();
|
||||||
|
}
|
||||||
|
|
||||||
|
self._munger
|
||||||
|
// Ignore passed `is_top_level` option since platform itself doesn't know
|
||||||
|
// anything about managing dependencies - it's responsibility of caller.
|
||||||
|
.add_plugin_changes(plugin, installOptions.variables, /*is_top_level=*/true, /*should_increment=*/true)
|
||||||
|
.save_all();
|
||||||
|
|
||||||
|
var targetDir = installOptions.usePlatformWww ?
|
||||||
|
self.locations.platformWww :
|
||||||
|
self.locations.www;
|
||||||
|
|
||||||
|
self._addModulesInfo(plugin, targetDir);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes an installed plugin from platform.
|
||||||
|
*
|
||||||
|
* Since method accepts PluginInfo instance as input parameter instead of plugin
|
||||||
|
* id, caller shoud take care of managing/storing PluginInfo instances for
|
||||||
|
* future uninstalls.
|
||||||
|
*
|
||||||
|
* @param {PluginInfo} plugin A PluginInfo instance that represents plugin
|
||||||
|
* that will be installed.
|
||||||
|
*
|
||||||
|
* @return {Promise} Return a promise either fulfilled, or rejected with
|
||||||
|
* CordovaError instance.
|
||||||
|
*/
|
||||||
|
Api.prototype.removePlugin = function (plugin, uninstallOptions) {
|
||||||
|
|
||||||
|
if (!plugin || plugin.constructor.name !== 'PluginInfo')
|
||||||
|
return Q.reject(new CordovaError('The parameter is incorrect. The first parameter to addPlugin should be a PluginInfo instance'));
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
var actions = new ActionStack();
|
||||||
|
var project = AndroidProject.getProjectFile(this.root);
|
||||||
|
|
||||||
|
// queue up plugin files
|
||||||
|
plugin.getFilesAndFrameworks(this.platform)
|
||||||
|
.concat(plugin.getAssets(this.platform))
|
||||||
|
.concat(plugin.getJsModules(this.platform))
|
||||||
|
.forEach(function(item) {
|
||||||
|
actions.push(actions.createAction(
|
||||||
|
pluginHandlers.getUninstaller(item.itemType), [item, plugin, project, uninstallOptions],
|
||||||
|
pluginHandlers.getInstaller(item.itemType), [item, plugin, project, uninstallOptions]));
|
||||||
|
});
|
||||||
|
|
||||||
|
// run through the action stack
|
||||||
|
return actions.process(this.platform)
|
||||||
|
.then(function() {
|
||||||
|
if (project) {
|
||||||
|
project.write();
|
||||||
|
}
|
||||||
|
|
||||||
|
self._munger
|
||||||
|
// Ignore passed `is_top_level` option since platform itself doesn't know
|
||||||
|
// anything about managing dependencies - it's responsibility of caller.
|
||||||
|
.remove_plugin_changes(plugin, /*is_top_level=*/true)
|
||||||
|
.save_all();
|
||||||
|
|
||||||
|
var targetDir = uninstallOptions.usePlatformWww ?
|
||||||
|
self.locations.platformWww :
|
||||||
|
self.locations.www;
|
||||||
|
|
||||||
|
self._removeModulesInfo(plugin, targetDir);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds an application package for current platform.
|
||||||
|
*
|
||||||
|
* @param {Object} buildOptions A build options. This object's structure is
|
||||||
|
* highly depends on platform's specific. The most common options are:
|
||||||
|
* @param {Boolean} buildOptions.debug Indicates that packages should be
|
||||||
|
* built with debug configuration. This is set to true by default unless the
|
||||||
|
* 'release' option is not specified.
|
||||||
|
* @param {Boolean} buildOptions.release Indicates that packages should be
|
||||||
|
* built with release configuration. If not set to true, debug configuration
|
||||||
|
* will be used.
|
||||||
|
* @param {Boolean} buildOptions.device Specifies that built app is intended
|
||||||
|
* to run on device
|
||||||
|
* @param {Boolean} buildOptions.emulator: Specifies that built app is
|
||||||
|
* intended to run on emulator
|
||||||
|
* @param {String} buildOptions.target Specifies the device id that will be
|
||||||
|
* used to run built application.
|
||||||
|
* @param {Boolean} buildOptions.nobuild Indicates that this should be a
|
||||||
|
* dry-run call, so no build artifacts will be produced.
|
||||||
|
* @param {String[]} buildOptions.archs Specifies chip architectures which
|
||||||
|
* app packages should be built for. List of valid architectures is depends on
|
||||||
|
* platform.
|
||||||
|
* @param {String} buildOptions.buildConfig The path to build configuration
|
||||||
|
* file. The format of this file is depends on platform.
|
||||||
|
* @param {String[]} buildOptions.argv Raw array of command-line arguments,
|
||||||
|
* passed to `build` command. The purpose of this property is to pass a
|
||||||
|
* platform-specific arguments, and eventually let platform define own
|
||||||
|
* arguments processing logic.
|
||||||
|
*
|
||||||
|
* @return {Promise<Object[]>} A promise either fulfilled with an array of build
|
||||||
|
* artifacts (application packages) if package was built successfully,
|
||||||
|
* or rejected with CordovaError. The resultant build artifact objects is not
|
||||||
|
* strictly typed and may conatin arbitrary set of fields as in sample below.
|
||||||
|
*
|
||||||
|
* {
|
||||||
|
* architecture: 'x86',
|
||||||
|
* buildType: 'debug',
|
||||||
|
* path: '/path/to/build',
|
||||||
|
* type: 'app'
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* The return value in most cases will contain only one item but in some cases
|
||||||
|
* there could be multiple items in output array, e.g. when multiple
|
||||||
|
* arhcitectures is specified.
|
||||||
|
*/
|
||||||
|
Api.prototype.build = function (buildOptions) {
|
||||||
|
var self = this;
|
||||||
|
return require('./lib/check_reqs').run()
|
||||||
|
.then(function () {
|
||||||
|
return require('./lib/build').run.call(self, buildOptions);
|
||||||
|
})
|
||||||
|
.then(function (buildResults) {
|
||||||
|
// Cast build result to array of build artifacts
|
||||||
|
return buildResults.apkPaths.map(function (apkPath) {
|
||||||
|
return {
|
||||||
|
buildType: buildResults.buildType,
|
||||||
|
buildMethod: buildResults.buildMethod,
|
||||||
|
path: apkPath,
|
||||||
|
type: 'apk'
|
||||||
|
};
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds an application package for current platform and runs it on
|
||||||
|
* specified/default device. If no 'device'/'emulator'/'target' options are
|
||||||
|
* specified, then tries to run app on default device if connected, otherwise
|
||||||
|
* runs the app on emulator.
|
||||||
|
*
|
||||||
|
* @param {Object} runOptions An options object. The structure is the same
|
||||||
|
* as for build options.
|
||||||
|
*
|
||||||
|
* @return {Promise} A promise either fulfilled if package was built and ran
|
||||||
|
* successfully, or rejected with CordovaError.
|
||||||
|
*/
|
||||||
|
Api.prototype.run = function(runOptions) {
|
||||||
|
var self = this;
|
||||||
|
return require('./lib/check_reqs').run()
|
||||||
|
.then(function () {
|
||||||
|
return require('./lib/run').run.call(self, runOptions);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cleans out the build artifacts from platform's directory.
|
||||||
|
*
|
||||||
|
* @return {Promise} Return a promise either fulfilled, or rejected with
|
||||||
|
* CordovaError.
|
||||||
|
*/
|
||||||
|
Api.prototype.clean = function(cleanOptions) {
|
||||||
|
var self = this;
|
||||||
|
return require('./lib/check_reqs').run()
|
||||||
|
.then(function () {
|
||||||
|
return require('./lib/build').runClean.call(self, cleanOptions);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs a requirements check for current platform. Each platform defines its
|
||||||
|
* own set of requirements, which should be resolved before platform can be
|
||||||
|
* built successfully.
|
||||||
|
*
|
||||||
|
* @return {Promise<Requirement[]>} Promise, resolved with set of Requirement
|
||||||
|
* objects for current platform.
|
||||||
|
*/
|
||||||
|
Api.prototype.requirements = function() {
|
||||||
|
return require('./lib/check_reqs').check_all();
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = Api;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the specified modules from list of installed modules and updates
|
||||||
|
* platform_json and cordova_plugins.js on disk.
|
||||||
|
*
|
||||||
|
* @param {PluginInfo} plugin PluginInfo instance for plugin, which modules
|
||||||
|
* needs to be added.
|
||||||
|
* @param {String} targetDir The directory, where updated cordova_plugins.js
|
||||||
|
* should be written to.
|
||||||
|
*/
|
||||||
|
Api.prototype._addModulesInfo = function(plugin, targetDir) {
|
||||||
|
var installedModules = this._platformJson.root.modules || [];
|
||||||
|
|
||||||
|
var installedPaths = installedModules.map(function (installedModule) {
|
||||||
|
return installedModule.file;
|
||||||
|
});
|
||||||
|
|
||||||
|
var modulesToInstall = plugin.getJsModules(this.platform)
|
||||||
|
.filter(function (moduleToInstall) {
|
||||||
|
return installedPaths.indexOf(moduleToInstall.file) === -1;
|
||||||
|
}).map(function (moduleToInstall) {
|
||||||
|
var moduleName = plugin.id + '.' + ( moduleToInstall.name || moduleToInstall.src.match(/([^\/]+)\.js/)[1] );
|
||||||
|
var obj = {
|
||||||
|
file: ['plugins', plugin.id, moduleToInstall.src].join('/'),
|
||||||
|
id: moduleName
|
||||||
|
};
|
||||||
|
if (moduleToInstall.clobbers.length > 0) {
|
||||||
|
obj.clobbers = moduleToInstall.clobbers.map(function(o) { return o.target; });
|
||||||
|
}
|
||||||
|
if (moduleToInstall.merges.length > 0) {
|
||||||
|
obj.merges = moduleToInstall.merges.map(function(o) { return o.target; });
|
||||||
|
}
|
||||||
|
if (moduleToInstall.runs) {
|
||||||
|
obj.runs = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
});
|
||||||
|
|
||||||
|
this._platformJson.root.modules = installedModules.concat(modulesToInstall);
|
||||||
|
this._writePluginModules(targetDir);
|
||||||
|
this._platformJson.save();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the specified modules from list of installed modules and updates
|
||||||
|
* platform_json and cordova_plugins.js on disk.
|
||||||
|
*
|
||||||
|
* @param {PluginInfo} plugin PluginInfo instance for plugin, which modules
|
||||||
|
* needs to be removed.
|
||||||
|
* @param {String} targetDir The directory, where updated cordova_plugins.js
|
||||||
|
* should be written to.
|
||||||
|
*/
|
||||||
|
Api.prototype._removeModulesInfo = function(plugin, targetDir) {
|
||||||
|
var installedModules = this._platformJson.root.modules || [];
|
||||||
|
var modulesToRemove = plugin.getJsModules(this.platform)
|
||||||
|
.map(function (jsModule) {
|
||||||
|
return ['plugins', plugin.id, jsModule.src].join('/');
|
||||||
|
});
|
||||||
|
|
||||||
|
var updatedModules = installedModules
|
||||||
|
.filter(function (installedModule) {
|
||||||
|
return (modulesToRemove.indexOf(installedModule.file) === -1);
|
||||||
|
});
|
||||||
|
|
||||||
|
this._platformJson.root.modules = updatedModules;
|
||||||
|
this._writePluginModules(targetDir);
|
||||||
|
this._platformJson.save();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches all installed modules, generates cordova_plugins contents and writes
|
||||||
|
* it to file.
|
||||||
|
*
|
||||||
|
* @param {String} targetDir Directory, where write cordova_plugins.js to.
|
||||||
|
* Ususally it is either <platform>/www or <platform>/platform_www
|
||||||
|
* directories.
|
||||||
|
*/
|
||||||
|
Api.prototype._writePluginModules = function (targetDir) {
|
||||||
|
var self = this;
|
||||||
|
// Write out moduleObjects as JSON wrapped in a cordova module to cordova_plugins.js
|
||||||
|
var final_contents = 'cordova.define(\'cordova/plugin_list\', function(require, exports, module) {\n';
|
||||||
|
final_contents += 'module.exports = ' + JSON.stringify(this._platformJson.root.modules, null, ' ') + ';\n';
|
||||||
|
final_contents += 'module.exports.metadata = \n';
|
||||||
|
final_contents += '// TOP OF METADATA\n';
|
||||||
|
|
||||||
|
var pluginMetadata = Object.keys(this._platformJson.root.installed_plugins)
|
||||||
|
.reduce(function (metadata, plugin) {
|
||||||
|
metadata[plugin] = self._platformJson.root.installed_plugins[plugin].version;
|
||||||
|
return metadata;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
final_contents += JSON.stringify(pluginMetadata, null, 4) + '\n';
|
||||||
|
final_contents += '// BOTTOM OF METADATA\n';
|
||||||
|
final_contents += '});'; // Close cordova.define.
|
||||||
|
|
||||||
|
shell.mkdir('-p', targetDir);
|
||||||
|
fs.writeFileSync(path.join(targetDir, 'cordova_plugins.js'), final_contents, 'utf-8');
|
||||||
|
};
|
@ -19,23 +19,30 @@
|
|||||||
under the License.
|
under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var build = require('./lib/build'),
|
var args = process.argv;
|
||||||
reqs = require('./lib/check_reqs'),
|
var Api = require('./Api');
|
||||||
args = process.argv;
|
var nopt = require('nopt');
|
||||||
|
var path = require('path');
|
||||||
|
|
||||||
// Support basic help commands
|
// Support basic help commands
|
||||||
if(args[2] == '--help' ||
|
if(['--help', '/?', '-h', 'help', '-help', '/help'].indexOf(process.argv[2]) >= 0)
|
||||||
args[2] == '/?' ||
|
require('./lib/build').help();
|
||||||
args[2] == '-h' ||
|
|
||||||
args[2] == 'help' ||
|
// Do some basic argument parsing
|
||||||
args[2] == '-help' ||
|
var buildOpts = nopt({
|
||||||
args[2] == '/help') {
|
'verbose' : Boolean,
|
||||||
build.help();
|
'silent' : Boolean,
|
||||||
} else {
|
'debug' : Boolean,
|
||||||
reqs.run().done(function() {
|
'release' : Boolean,
|
||||||
return build.run(args.slice(2));
|
'nobuild': Boolean,
|
||||||
}, function(err) {
|
'buildConfig' : path
|
||||||
console.error(err);
|
}, { 'd' : '--verbose' });
|
||||||
process.exit(2);
|
|
||||||
});
|
// Make buildOptions compatible with PlatformApi build method spec
|
||||||
}
|
buildOpts.argv = buildOpts.argv.remain;
|
||||||
|
|
||||||
|
new Api().build(buildOpts)
|
||||||
|
.catch(function(err) {
|
||||||
|
console.error(err.stack);
|
||||||
|
process.exit(2);
|
||||||
|
});
|
||||||
|
@ -19,26 +19,18 @@
|
|||||||
under the License.
|
under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var build = require('./lib/build'),
|
var Api = require('./Api');
|
||||||
reqs = require('./lib/check_reqs'),
|
|
||||||
args = process.argv;
|
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
|
|
||||||
// Support basic help commands
|
// Support basic help commands
|
||||||
if(args[2] == '--help' ||
|
if(['--help', '/?', '-h', 'help', '-help', '/help'].indexOf(process.argv[2]) >= 0) {
|
||||||
args[2] == '/?' ||
|
|
||||||
args[2] == '-h' ||
|
|
||||||
args[2] == 'help' ||
|
|
||||||
args[2] == '-help' ||
|
|
||||||
args[2] == '/help') {
|
|
||||||
console.log('Usage: ' + path.relative(process.cwd(), process.argv[1]));
|
console.log('Usage: ' + path.relative(process.cwd(), process.argv[1]));
|
||||||
console.log('Cleans the project directory.');
|
console.log('Cleans the project directory.');
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
} else {
|
|
||||||
reqs.run().done(function() {
|
|
||||||
return build.runClean(args.slice(2));
|
|
||||||
}, function(err) {
|
|
||||||
console.error(err);
|
|
||||||
process.exit(2);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
new Api().clean({argv: process.argv.slice(2)})
|
||||||
|
.catch(function(err) {
|
||||||
|
console.error(err.stack);
|
||||||
|
process.exit(2);
|
||||||
|
});
|
||||||
|
78
bin/templates/cordova/lib/Adb.js
vendored
Normal file
78
bin/templates/cordova/lib/Adb.js
vendored
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
|
||||||
|
var Q = require('q');
|
||||||
|
var os = require('os');
|
||||||
|
var events = require('cordova-common').events;
|
||||||
|
var spawn = require('cordova-common').superspawn.spawn;
|
||||||
|
var CordovaError = require('cordova-common').CordovaError;
|
||||||
|
|
||||||
|
var Adb = {};
|
||||||
|
|
||||||
|
function isDevice(line) {
|
||||||
|
return line.match(/\w+\tdevice/) && !line.match(/emulator/);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isEmulator(line) {
|
||||||
|
return line.match(/device/) && line.match(/emulator/);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lists available/connected devices and emulators
|
||||||
|
*
|
||||||
|
* @param {Object} opts Various options
|
||||||
|
* @param {Boolean} opts.emulators Specifies whether this method returns
|
||||||
|
* emulators only
|
||||||
|
*
|
||||||
|
* @return {Promise<String[]>} list of available/connected
|
||||||
|
* devices/emulators
|
||||||
|
*/
|
||||||
|
Adb.devices = function (opts) {
|
||||||
|
return spawn('adb', ['devices'], {cwd: os.tmpdir()})
|
||||||
|
.then(function(output) {
|
||||||
|
return output.split('\n').filter(function (line) {
|
||||||
|
// Filter out either real devices or emulators, depending on options
|
||||||
|
return (line && opts && opts.emulators) ? isEmulator(line) : isDevice(line);
|
||||||
|
}).map(function (line) {
|
||||||
|
return line.replace(/\tdevice/, '').replace('\r', '');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Adb.install = function (target, packagePath, opts) {
|
||||||
|
events.emit('verbose', 'Installing apk ' + packagePath + ' on ' + target + '...');
|
||||||
|
var args = ['-s', target, 'install'];
|
||||||
|
if (opts && opts.replace) args.push('-r');
|
||||||
|
return spawn('adb', args.concat(packagePath), {cwd: os.tmpdir()})
|
||||||
|
.then(function(output) {
|
||||||
|
// 'adb install' seems to always returns no error, even if installation fails
|
||||||
|
// so we catching output to detect installation failure
|
||||||
|
if (output.match(/Failure/))
|
||||||
|
return Q.reject(new CordovaError('Failed to install apk to device: ' + output));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Adb.uninstall = function (target, packageId) {
|
||||||
|
events.emit('verbose', 'Uninstalling ' + packageId + ' from ' + target + '...');
|
||||||
|
return spawn('adb', ['-s', target, 'uninstall', packageId], {cwd: os.tmpdir()});
|
||||||
|
};
|
||||||
|
|
||||||
|
Adb.shell = function (target, shellCommand) {
|
||||||
|
events.emit('verbose', 'Running command "' + shellCommand + '" on ' + target + '...');
|
||||||
|
var args = ['-s', target, 'shell'];
|
||||||
|
shellCommand = shellCommand.split(/\s+/);
|
||||||
|
return spawn('adb', args.concat(shellCommand), {cwd: os.tmpdir()})
|
||||||
|
.catch(function (output) {
|
||||||
|
return Q.reject(new CordovaError('Failed to execute shell command "' +
|
||||||
|
shellCommand + '"" on device: ' + output));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Adb.start = function (target, activityName) {
|
||||||
|
events.emit('verbose', 'Starting application "' + activityName + '" on ' + target + '...');
|
||||||
|
return Adb.shell(target, 'am start -W -a android.intent.action.MAIN -n' + activityName)
|
||||||
|
.catch(function (output) {
|
||||||
|
return Q.reject(new CordovaError('Failed to start application "' +
|
||||||
|
activityName + '"" on device: ' + output));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = Adb;
|
161
bin/templates/cordova/lib/AndroidManifest.js
vendored
Normal file
161
bin/templates/cordova/lib/AndroidManifest.js
vendored
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
/**
|
||||||
|
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 fs = require('fs');
|
||||||
|
var et = require('elementtree');
|
||||||
|
var xml= require('cordova-common').xmlHelpers;
|
||||||
|
|
||||||
|
var DEFAULT_ORIENTATION = 'default';
|
||||||
|
|
||||||
|
/** Wraps an AndroidManifest file */
|
||||||
|
function AndroidManifest(path) {
|
||||||
|
this.path = path;
|
||||||
|
this.doc = xml.parseElementtreeSync(path);
|
||||||
|
if (this.doc.getroot().tag !== 'manifest') {
|
||||||
|
throw new Error(path + ' has incorrect root node name (expected "manifest")');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AndroidManifest.prototype.getVersionName = function() {
|
||||||
|
return this.doc.getroot().attrib['android:versionName'];
|
||||||
|
};
|
||||||
|
|
||||||
|
AndroidManifest.prototype.setVersionName = function(versionName) {
|
||||||
|
this.doc.getroot().attrib['android:versionName'] = versionName;
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
AndroidManifest.prototype.getVersionCode = function() {
|
||||||
|
return this.doc.getroot().attrib['android:versionCode'];
|
||||||
|
};
|
||||||
|
|
||||||
|
AndroidManifest.prototype.setVersionCode = function(versionCode) {
|
||||||
|
this.doc.getroot().attrib['android:versionCode'] = versionCode;
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
AndroidManifest.prototype.getPackageId = function() {
|
||||||
|
/*jshint -W069 */
|
||||||
|
return this.doc.getroot().attrib['package'];
|
||||||
|
/*jshint +W069 */
|
||||||
|
};
|
||||||
|
|
||||||
|
AndroidManifest.prototype.setPackageId = function(pkgId) {
|
||||||
|
/*jshint -W069 */
|
||||||
|
this.doc.getroot().attrib['package'] = pkgId;
|
||||||
|
/*jshint +W069 */
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
AndroidManifest.prototype.getActivity = function() {
|
||||||
|
var activity = this.doc.getroot().find('./application/activity');
|
||||||
|
return {
|
||||||
|
getName: function () {
|
||||||
|
return activity.attrib['android:name'];
|
||||||
|
},
|
||||||
|
setName: function (name) {
|
||||||
|
if (!name) {
|
||||||
|
delete activity.attrib['android:name'];
|
||||||
|
} else {
|
||||||
|
activity.attrib['android:name'] = name;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
getOrientation: function () {
|
||||||
|
return activity.attrib['android:screenOrientation'];
|
||||||
|
},
|
||||||
|
setOrientation: function (orientation) {
|
||||||
|
if (!orientation || orientation.toLowerCase() === DEFAULT_ORIENTATION) {
|
||||||
|
delete activity.attrib['android:screenOrientation'];
|
||||||
|
} else {
|
||||||
|
activity.attrib['android:screenOrientation'] = orientation;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
getLaunchMode: function () {
|
||||||
|
return activity.attrib['android:launchMode'];
|
||||||
|
},
|
||||||
|
setLaunchMode: function (launchMode) {
|
||||||
|
if (!launchMode) {
|
||||||
|
delete activity.attrib['android:launchMode'];
|
||||||
|
} else {
|
||||||
|
activity.attrib['android:launchMode'] = launchMode;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
['minSdkVersion', 'maxSdkVersion', 'targetSdkVersion']
|
||||||
|
.forEach(function(sdkPrefName) {
|
||||||
|
// Copy variable reference to avoid closure issues
|
||||||
|
var prefName = sdkPrefName;
|
||||||
|
|
||||||
|
AndroidManifest.prototype['get' + capitalize(prefName)] = function() {
|
||||||
|
var usesSdk = this.doc.getroot().find('./uses-sdk');
|
||||||
|
return usesSdk && usesSdk.attrib['android:' + prefName];
|
||||||
|
};
|
||||||
|
|
||||||
|
AndroidManifest.prototype['set' + capitalize(prefName)] = function(prefValue) {
|
||||||
|
var usesSdk = this.doc.getroot().find('./uses-sdk');
|
||||||
|
|
||||||
|
if (!usesSdk && prefValue) { // if there is no required uses-sdk element, we should create it first
|
||||||
|
usesSdk = new et.Element('uses-sdk');
|
||||||
|
this.doc.getroot().append(usesSdk);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prefValue) {
|
||||||
|
usesSdk.attrib['android:' + prefName] = prefValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
AndroidManifest.prototype.getDebuggable = function() {
|
||||||
|
return this.doc.getroot().find('./application').attrib['android:debuggable'] === 'true';
|
||||||
|
};
|
||||||
|
|
||||||
|
AndroidManifest.prototype.setDebuggable = function(value) {
|
||||||
|
var application = this.doc.getroot().find('./application');
|
||||||
|
if (value) {
|
||||||
|
application.attrib['android:debuggable'] = 'true';
|
||||||
|
} else {
|
||||||
|
// The default value is "false", so we can remove attribute at all.
|
||||||
|
delete application.attrib['android:debuggable'];
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes manifest to disk syncronously. If filename is specified, then manifest
|
||||||
|
* will be written to that file
|
||||||
|
*
|
||||||
|
* @param {String} [destPath] File to write manifest to. If omitted,
|
||||||
|
* manifest will be written to file it has been read from.
|
||||||
|
*/
|
||||||
|
AndroidManifest.prototype.write = function(destPath) {
|
||||||
|
fs.writeFileSync(destPath || this.path, this.doc.write({indent: 4}), 'utf-8');
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = AndroidManifest;
|
||||||
|
|
||||||
|
function capitalize (str) {
|
||||||
|
return str.charAt(0).toUpperCase() + str.slice(1);
|
||||||
|
}
|
184
bin/templates/cordova/lib/AndroidProject.js
vendored
Normal file
184
bin/templates/cordova/lib/AndroidProject.js
vendored
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
/**
|
||||||
|
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 fs = require('fs');
|
||||||
|
var path = require('path');
|
||||||
|
var properties_parser = require('properties-parser');
|
||||||
|
var AndroidManifest = require('./AndroidManifest');
|
||||||
|
|
||||||
|
var projectFileCache = {};
|
||||||
|
|
||||||
|
function addToPropertyList(projectProperties, key, value) {
|
||||||
|
var i = 1;
|
||||||
|
while (projectProperties.get(key + '.' + i))
|
||||||
|
i++;
|
||||||
|
|
||||||
|
projectProperties.set(key + '.' + i, value);
|
||||||
|
projectProperties.dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeFromPropertyList(projectProperties, key, value) {
|
||||||
|
var i = 1;
|
||||||
|
var currentValue;
|
||||||
|
while ((currentValue = projectProperties.get(key + '.' + i))) {
|
||||||
|
if (currentValue === value) {
|
||||||
|
while ((currentValue = projectProperties.get(key + '.' + (i + 1)))) {
|
||||||
|
projectProperties.set(key + '.' + i, currentValue);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
projectProperties.set(key + '.' + i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
projectProperties.dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRelativeLibraryPath (parentDir, subDir) {
|
||||||
|
var libraryPath = path.relative(parentDir, subDir);
|
||||||
|
return (path.sep == '\\') ? libraryPath.replace(/\\/g, '/') : libraryPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
function AndroidProject(projectDir) {
|
||||||
|
this._propertiesEditors = {};
|
||||||
|
this._subProjectDirs = {};
|
||||||
|
this._dirty = false;
|
||||||
|
this.projectDir = projectDir;
|
||||||
|
this.platformWww = path.join(this.projectDir, 'platform_www');
|
||||||
|
this.www = path.join(this.projectDir, 'assets/www');
|
||||||
|
}
|
||||||
|
|
||||||
|
AndroidProject.getProjectFile = function (projectDir) {
|
||||||
|
if (!projectFileCache[projectDir]) {
|
||||||
|
projectFileCache[projectDir] = new AndroidProject(projectDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
return projectFileCache[projectDir];
|
||||||
|
};
|
||||||
|
|
||||||
|
AndroidProject.purgeCache = function (projectDir) {
|
||||||
|
if (projectDir) {
|
||||||
|
delete projectFileCache[projectDir];
|
||||||
|
} else {
|
||||||
|
projectFileCache = {};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the package name out of the Android Manifest file
|
||||||
|
*
|
||||||
|
* @param {String} projectDir The absolute path to the directory containing the project
|
||||||
|
*
|
||||||
|
* @return {String} The name of the package
|
||||||
|
*/
|
||||||
|
AndroidProject.prototype.getPackageName = function() {
|
||||||
|
return new AndroidManifest(path.join(this.projectDir, 'AndroidManifest.xml')).getPackageId();
|
||||||
|
};
|
||||||
|
|
||||||
|
AndroidProject.prototype.getCustomSubprojectRelativeDir = function(plugin_id, src) {
|
||||||
|
// All custom subprojects are prefixed with the last portion of the package id.
|
||||||
|
// This is to avoid collisions when opening multiple projects in Eclipse that have subprojects with the same name.
|
||||||
|
var packageName = this.getPackageName();
|
||||||
|
var lastDotIndex = packageName.lastIndexOf('.');
|
||||||
|
var prefix = packageName.substring(lastDotIndex + 1);
|
||||||
|
var subRelativeDir = path.join(plugin_id, prefix + '-' + path.basename(src));
|
||||||
|
return subRelativeDir;
|
||||||
|
};
|
||||||
|
|
||||||
|
AndroidProject.prototype.addSubProject = function(parentDir, subDir) {
|
||||||
|
var parentProjectFile = path.resolve(parentDir, 'project.properties');
|
||||||
|
var subProjectFile = path.resolve(subDir, 'project.properties');
|
||||||
|
var parentProperties = this._getPropertiesFile(parentProjectFile);
|
||||||
|
// TODO: Setting the target needs to happen only for pre-3.7.0 projects
|
||||||
|
if (fs.existsSync(subProjectFile)) {
|
||||||
|
var subProperties = this._getPropertiesFile(subProjectFile);
|
||||||
|
subProperties.set('target', parentProperties.get('target'));
|
||||||
|
subProperties.dirty = true;
|
||||||
|
this._subProjectDirs[subDir] = true;
|
||||||
|
}
|
||||||
|
addToPropertyList(parentProperties, 'android.library.reference', getRelativeLibraryPath(parentDir, subDir));
|
||||||
|
|
||||||
|
this._dirty = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
AndroidProject.prototype.removeSubProject = function(parentDir, subDir) {
|
||||||
|
var parentProjectFile = path.resolve(parentDir, 'project.properties');
|
||||||
|
var parentProperties = this._getPropertiesFile(parentProjectFile);
|
||||||
|
removeFromPropertyList(parentProperties, 'android.library.reference', getRelativeLibraryPath(parentDir, subDir));
|
||||||
|
delete this._subProjectDirs[subDir];
|
||||||
|
this._dirty = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
AndroidProject.prototype.addGradleReference = function(parentDir, subDir) {
|
||||||
|
var parentProjectFile = path.resolve(parentDir, 'project.properties');
|
||||||
|
var parentProperties = this._getPropertiesFile(parentProjectFile);
|
||||||
|
addToPropertyList(parentProperties, 'cordova.gradle.include', getRelativeLibraryPath(parentDir, subDir));
|
||||||
|
this._dirty = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
AndroidProject.prototype.removeGradleReference = function(parentDir, subDir) {
|
||||||
|
var parentProjectFile = path.resolve(parentDir, 'project.properties');
|
||||||
|
var parentProperties = this._getPropertiesFile(parentProjectFile);
|
||||||
|
removeFromPropertyList(parentProperties, 'cordova.gradle.include', getRelativeLibraryPath(parentDir, subDir));
|
||||||
|
this._dirty = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
AndroidProject.prototype.addSystemLibrary = function(parentDir, value) {
|
||||||
|
var parentProjectFile = path.resolve(parentDir, 'project.properties');
|
||||||
|
var parentProperties = this._getPropertiesFile(parentProjectFile);
|
||||||
|
addToPropertyList(parentProperties, 'cordova.system.library', value);
|
||||||
|
this._dirty = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
AndroidProject.prototype.removeSystemLibrary = function(parentDir, value) {
|
||||||
|
var parentProjectFile = path.resolve(parentDir, 'project.properties');
|
||||||
|
var parentProperties = this._getPropertiesFile(parentProjectFile);
|
||||||
|
removeFromPropertyList(parentProperties, 'cordova.system.library', value);
|
||||||
|
this._dirty = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
AndroidProject.prototype.write = function() {
|
||||||
|
if (!this._dirty) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._dirty = false;
|
||||||
|
|
||||||
|
for (var filename in this._propertiesEditors) {
|
||||||
|
var editor = this._propertiesEditors[filename];
|
||||||
|
if (editor.dirty) {
|
||||||
|
fs.writeFileSync(filename, editor.toString());
|
||||||
|
editor.dirty = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
AndroidProject.prototype._getPropertiesFile = function (filename) {
|
||||||
|
if (!this._propertiesEditors[filename]) {
|
||||||
|
if (fs.existsSync(filename)) {
|
||||||
|
this._propertiesEditors[filename] = properties_parser.createEditor(filename);
|
||||||
|
} else {
|
||||||
|
this._propertiesEditors[filename] = properties_parser.createEditor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return this._propertiesEditors[filename];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = AndroidProject;
|
75
bin/templates/cordova/lib/ConsoleLogger.js
vendored
Normal file
75
bin/templates/cordova/lib/ConsoleLogger.js
vendored
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
/**
|
||||||
|
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 loggerInstance;
|
||||||
|
var util = require('util');
|
||||||
|
var EventEmitter = require('events').EventEmitter;
|
||||||
|
var CordovaError = require('cordova-common').CordovaError;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class ConsoleLogger
|
||||||
|
* @extends EventEmitter
|
||||||
|
*
|
||||||
|
* Implementing basic logging for platform. Inherits regular NodeJS
|
||||||
|
* EventEmitter. All events, emitted on this class instance are immediately
|
||||||
|
* logged to console.
|
||||||
|
*
|
||||||
|
* Also attaches handler to process' uncaught exceptions, so these exceptions
|
||||||
|
* logged to console similar to regular error events.
|
||||||
|
*/
|
||||||
|
function ConsoleLogger() {
|
||||||
|
EventEmitter.call(this);
|
||||||
|
|
||||||
|
var isVerbose = process.argv.indexOf('-d') >= 0 || process.argv.indexOf('--verbose') >= 0;
|
||||||
|
// For CordovaError print only the message without stack trace unless we
|
||||||
|
// are in a verbose mode.
|
||||||
|
process.on('uncaughtException', function(err){
|
||||||
|
if ((err instanceof CordovaError) && isVerbose) {
|
||||||
|
console.error(err.stack);
|
||||||
|
} else {
|
||||||
|
console.error(err.message);
|
||||||
|
}
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.on('results', console.log);
|
||||||
|
this.on('verbose', function () {
|
||||||
|
if (isVerbose)
|
||||||
|
console.log.apply(console, arguments);
|
||||||
|
});
|
||||||
|
this.on('info', console.log);
|
||||||
|
this.on('log', console.log);
|
||||||
|
this.on('warn', console.warn);
|
||||||
|
}
|
||||||
|
util.inherits(ConsoleLogger, EventEmitter);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns already instantiated/newly created instance of ConsoleLogger class.
|
||||||
|
* This method should be used instead of creating ConsoleLogger directly,
|
||||||
|
* otherwise we'll get multiple handlers attached to process'
|
||||||
|
* uncaughtException
|
||||||
|
*
|
||||||
|
* @return {ConsoleLogger} New or already created instance of ConsoleLogger
|
||||||
|
*/
|
||||||
|
ConsoleLogger.get = function () {
|
||||||
|
loggerInstance = loggerInstance || new ConsoleLogger();
|
||||||
|
return loggerInstance;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = ConsoleLogger;
|
48
bin/templates/cordova/lib/appinfo.js
vendored
48
bin/templates/cordova/lib/appinfo.js
vendored
@ -1,48 +0,0 @@
|
|||||||
#!/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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var path = require('path');
|
|
||||||
var fs = require('fs');
|
|
||||||
var cachedAppInfo = null;
|
|
||||||
|
|
||||||
function readAppInfoFromManifest() {
|
|
||||||
var manifestPath = path.join(__dirname, '..', '..', 'AndroidManifest.xml');
|
|
||||||
var manifestData = fs.readFileSync(manifestPath, {encoding:'utf8'});
|
|
||||||
var packageName = /\bpackage\s*=\s*"(.+?)"/.exec(manifestData);
|
|
||||||
if (!packageName) throw new Error('Could not find package name within ' + manifestPath);
|
|
||||||
var activityTag = /<activity\b[\s\S]*<\/activity>/.exec(manifestData);
|
|
||||||
if (!activityTag) throw new Error('Could not find <activity> within ' + manifestPath);
|
|
||||||
var activityName = /\bandroid:name\s*=\s*"(.+?)"/.exec(activityTag);
|
|
||||||
if (!activityName) throw new Error('Could not find android:name within ' + manifestPath);
|
|
||||||
|
|
||||||
return (cachedAppInfo = {
|
|
||||||
packageName: packageName[1],
|
|
||||||
activityName: packageName[1] + '/.' + activityName[1]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.getActivityName = function() {
|
|
||||||
return cachedAppInfo ? cachedAppInfo.activityName : readAppInfoFromManifest().activityName;
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.getPackageName = function() {
|
|
||||||
return cachedAppInfo ? cachedAppInfo.packageName : readAppInfoFromManifest().packageName;
|
|
||||||
};
|
|
1017
bin/templates/cordova/lib/build.js
vendored
1017
bin/templates/cordova/lib/build.js
vendored
File diff suppressed because it is too large
Load Diff
141
bin/templates/cordova/lib/builders/AntBuilder.js
vendored
Normal file
141
bin/templates/cordova/lib/builders/AntBuilder.js
vendored
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
/*
|
||||||
|
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 Q = require('q');
|
||||||
|
var fs = require('fs');
|
||||||
|
var path = require('path');
|
||||||
|
var util = require('util');
|
||||||
|
var shell = require('shelljs');
|
||||||
|
var spawn = require('cordova-common').superspawn.spawn;
|
||||||
|
var CordovaError = require('cordova-common').CordovaError;
|
||||||
|
var check_reqs = require('../check_reqs');
|
||||||
|
|
||||||
|
var SIGNING_PROPERTIES = '-signing.properties';
|
||||||
|
var MARKER = 'YOUR CHANGES WILL BE ERASED!';
|
||||||
|
var TEMPLATE =
|
||||||
|
'# This file is automatically generated.\n' +
|
||||||
|
'# Do not modify this file -- ' + MARKER + '\n';
|
||||||
|
|
||||||
|
var GenericBuilder = require('./GenericBuilder');
|
||||||
|
|
||||||
|
function AntBuilder (projectRoot) {
|
||||||
|
GenericBuilder.call(this, projectRoot);
|
||||||
|
|
||||||
|
this.binDirs = {ant: this.binDirs.ant};
|
||||||
|
}
|
||||||
|
|
||||||
|
util.inherits(AntBuilder, GenericBuilder);
|
||||||
|
|
||||||
|
AntBuilder.prototype.getArgs = function(cmd, opts) {
|
||||||
|
var args = [cmd, '-f', path.join(this.root, 'build.xml')];
|
||||||
|
// custom_rules.xml is required for incremental builds.
|
||||||
|
if (hasCustomRules()) {
|
||||||
|
args.push('-Dout.dir=ant-build', '-Dgen.absolute.dir=ant-gen');
|
||||||
|
}
|
||||||
|
if(opts.packageInfo) {
|
||||||
|
args.push('-propertyfile=' + path.join(this.root, opts.buildType + SIGNING_PROPERTIES));
|
||||||
|
}
|
||||||
|
return args;
|
||||||
|
};
|
||||||
|
|
||||||
|
AntBuilder.prototype.prepEnv = function(opts) {
|
||||||
|
var self = this;
|
||||||
|
return check_reqs.check_ant()
|
||||||
|
.then(function() {
|
||||||
|
// Copy in build.xml on each build so that:
|
||||||
|
// A) we don't require the Android SDK at project creation time, and
|
||||||
|
// B) we always use the SDK's latest version of it.
|
||||||
|
/*jshint -W069 */
|
||||||
|
var sdkDir = process.env['ANDROID_HOME'];
|
||||||
|
/*jshint +W069 */
|
||||||
|
var buildTemplate = fs.readFileSync(path.join(sdkDir, 'tools', 'lib', 'build.template'), 'utf8');
|
||||||
|
function writeBuildXml(projectPath) {
|
||||||
|
var newData = buildTemplate.replace('PROJECT_NAME', self.extractRealProjectNameFromManifest());
|
||||||
|
fs.writeFileSync(path.join(projectPath, 'build.xml'), newData);
|
||||||
|
if (!fs.existsSync(path.join(projectPath, 'local.properties'))) {
|
||||||
|
fs.writeFileSync(path.join(projectPath, 'local.properties'), TEMPLATE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
writeBuildXml(self.root);
|
||||||
|
var propertiesObj = self.readProjectProperties();
|
||||||
|
var subProjects = propertiesObj.libs;
|
||||||
|
for (var i = 0; i < subProjects.length; ++i) {
|
||||||
|
writeBuildXml(path.join(self.root, subProjects[i]));
|
||||||
|
}
|
||||||
|
if (propertiesObj.systemLibs.length > 0) {
|
||||||
|
throw new CordovaError('Project contains at least one plugin that requires a system library. This is not supported with ANT. Please build using gradle.');
|
||||||
|
}
|
||||||
|
|
||||||
|
var propertiesFile = opts.buildType + SIGNING_PROPERTIES;
|
||||||
|
var propertiesFilePath = path.join(self.root, propertiesFile);
|
||||||
|
if (opts.packageInfo) {
|
||||||
|
fs.writeFileSync(propertiesFilePath, TEMPLATE + opts.packageInfo.toProperties());
|
||||||
|
} else if(isAutoGenerated(propertiesFilePath)) {
|
||||||
|
shell.rm('-f', propertiesFilePath);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Builds the project with ant.
|
||||||
|
* Returns a promise.
|
||||||
|
*/
|
||||||
|
AntBuilder.prototype.build = function(opts) {
|
||||||
|
// Without our custom_rules.xml, we need to clean before building.
|
||||||
|
var ret = Q();
|
||||||
|
if (!hasCustomRules()) {
|
||||||
|
// clean will call check_ant() for us.
|
||||||
|
ret = this.clean(opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
var args = this.getArgs(opts.buildType == 'debug' ? 'debug' : 'release', opts);
|
||||||
|
return check_reqs.check_ant()
|
||||||
|
.then(function() {
|
||||||
|
return spawn('ant', args, {stdio: 'inherit'});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
AntBuilder.prototype.clean = function(opts) {
|
||||||
|
var args = this.getArgs('clean', opts);
|
||||||
|
var self = this;
|
||||||
|
return check_reqs.check_ant()
|
||||||
|
.then(function() {
|
||||||
|
return spawn('ant', args, {stdio: 'inherit'});
|
||||||
|
})
|
||||||
|
.then(function () {
|
||||||
|
shell.rm('-rf', path.join(self.root, 'out'));
|
||||||
|
|
||||||
|
['debug', 'release'].forEach(function(config) {
|
||||||
|
var propertiesFilePath = path.join(self.root, config + SIGNING_PROPERTIES);
|
||||||
|
if(isAutoGenerated(propertiesFilePath)){
|
||||||
|
shell.rm('-f', propertiesFilePath);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = AntBuilder;
|
||||||
|
|
||||||
|
function hasCustomRules(projectRoot) {
|
||||||
|
return fs.existsSync(path.join(projectRoot, 'custom_rules.xml'));
|
||||||
|
}
|
||||||
|
|
||||||
|
function isAutoGenerated(file) {
|
||||||
|
return fs.existsSync(file) && fs.readFileSync(file, 'utf8').indexOf(MARKER) > 0;
|
||||||
|
}
|
138
bin/templates/cordova/lib/builders/GenericBuilder.js
vendored
Normal file
138
bin/templates/cordova/lib/builders/GenericBuilder.js
vendored
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
/*
|
||||||
|
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 Q = require('q');
|
||||||
|
var fs = require('fs');
|
||||||
|
var path = require('path');
|
||||||
|
var shell = require('shelljs');
|
||||||
|
var events = require('cordova-common').events;
|
||||||
|
var CordovaError = require('cordova-common').CordovaError;
|
||||||
|
|
||||||
|
function GenericBuilder (projectDir) {
|
||||||
|
this.root = projectDir || path.resolve(__dirname, '../../..');
|
||||||
|
this.binDirs = {
|
||||||
|
ant: path.join(this.root, hasCustomRules(this.root) ? 'ant-build' : 'bin'),
|
||||||
|
gradle: path.join(this.root, 'build', 'outputs', 'apk')
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function hasCustomRules(projectRoot) {
|
||||||
|
return fs.existsSync(path.join(projectRoot, 'custom_rules.xml'));
|
||||||
|
}
|
||||||
|
|
||||||
|
GenericBuilder.prototype.prepEnv = function() {
|
||||||
|
return Q();
|
||||||
|
};
|
||||||
|
|
||||||
|
GenericBuilder.prototype.build = function() {
|
||||||
|
events.emit('log', 'Skipping build...');
|
||||||
|
return Q(null);
|
||||||
|
};
|
||||||
|
|
||||||
|
GenericBuilder.prototype.clean = function() {
|
||||||
|
return Q();
|
||||||
|
};
|
||||||
|
|
||||||
|
GenericBuilder.prototype.findOutputApks = function(build_type, arch) {
|
||||||
|
var self = this;
|
||||||
|
return Object.keys(this.binDirs)
|
||||||
|
.reduce(function (result, builderName) {
|
||||||
|
var binDir = self.binDirs[builderName];
|
||||||
|
return result.concat(findOutputApksHelper(binDir, build_type, builderName === 'ant' ? null : arch));
|
||||||
|
}, [])
|
||||||
|
.sort(apkSorter);
|
||||||
|
};
|
||||||
|
|
||||||
|
GenericBuilder.prototype.readProjectProperties = function () {
|
||||||
|
function findAllUniq(data, r) {
|
||||||
|
var s = {};
|
||||||
|
var m;
|
||||||
|
while ((m = r.exec(data))) {
|
||||||
|
s[m[1]] = 1;
|
||||||
|
}
|
||||||
|
return Object.keys(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
var data = fs.readFileSync(path.join(this.root, 'project.properties'), 'utf8');
|
||||||
|
return {
|
||||||
|
libs: findAllUniq(data, /^\s*android\.library\.reference\.\d+=(.*)(?:\s|$)/mg),
|
||||||
|
gradleIncludes: findAllUniq(data, /^\s*cordova\.gradle\.include\.\d+=(.*)(?:\s|$)/mg),
|
||||||
|
systemLibs: findAllUniq(data, /^\s*cordova\.system\.library\.\d+=(.*)(?:\s|$)/mg)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
GenericBuilder.prototype.extractRealProjectNameFromManifest = function () {
|
||||||
|
var manifestPath = path.join(this.root, 'AndroidManifest.xml');
|
||||||
|
var manifestData = fs.readFileSync(manifestPath, 'utf8');
|
||||||
|
var m = /<manifest[\s\S]*?package\s*=\s*"(.*?)"/i.exec(manifestData);
|
||||||
|
if (!m) {
|
||||||
|
throw new CordovaError('Could not find package name in ' + manifestPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
var packageName=m[1];
|
||||||
|
var lastDotIndex = packageName.lastIndexOf('.');
|
||||||
|
return packageName.substring(lastDotIndex + 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = GenericBuilder;
|
||||||
|
|
||||||
|
function apkSorter(fileA, fileB) {
|
||||||
|
var timeDiff = fs.statSync(fileA).mtime - fs.statSync(fileB).mtime;
|
||||||
|
return timeDiff === 0 ? fileA.length - fileB.length : timeDiff;
|
||||||
|
}
|
||||||
|
|
||||||
|
function findOutputApksHelper(dir, build_type, arch) {
|
||||||
|
var shellSilent = shell.config.silent;
|
||||||
|
shell.config.silent = true;
|
||||||
|
|
||||||
|
var ret = shell.ls(path.join(dir, '*.apk'))
|
||||||
|
.filter(function(candidate) {
|
||||||
|
var apkName = path.basename(candidate);
|
||||||
|
// Need to choose between release and debug .apk.
|
||||||
|
if (build_type === 'debug') {
|
||||||
|
return /-debug/.exec(apkName) && !/-unaligned|-unsigned/.exec(apkName);
|
||||||
|
}
|
||||||
|
if (build_type === 'release') {
|
||||||
|
return /-release/.exec(apkName) && !/-unaligned/.exec(apkName);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
})
|
||||||
|
.sort(apkSorter);
|
||||||
|
|
||||||
|
shellSilent = shellSilent;
|
||||||
|
|
||||||
|
if (ret.length === 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
// Assume arch-specific build if newest apk has -x86 or -arm.
|
||||||
|
var archSpecific = !!/-x86|-arm/.exec(path.basename(ret[0]));
|
||||||
|
// And show only arch-specific ones (or non-arch-specific)
|
||||||
|
ret = ret.filter(function(p) {
|
||||||
|
/*jshint -W018 */
|
||||||
|
return !!/-x86|-arm/.exec(path.basename(p)) == archSpecific;
|
||||||
|
/*jshint +W018 */
|
||||||
|
});
|
||||||
|
if (archSpecific && ret.length > 1) {
|
||||||
|
ret = ret.filter(function(p) {
|
||||||
|
return path.basename(p).indexOf('-' + arch) != -1;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
213
bin/templates/cordova/lib/builders/GradleBuilder.js
vendored
Normal file
213
bin/templates/cordova/lib/builders/GradleBuilder.js
vendored
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
/*
|
||||||
|
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 Q = require('q');
|
||||||
|
var fs = require('fs');
|
||||||
|
var util = require('util');
|
||||||
|
var path = require('path');
|
||||||
|
var shell = require('shelljs');
|
||||||
|
var spawn = require('cordova-common').superspawn.spawn;
|
||||||
|
var CordovaError = require('cordova-common').CordovaError;
|
||||||
|
var check_reqs = require('../check_reqs');
|
||||||
|
|
||||||
|
var GenericBuilder = require('./GenericBuilder');
|
||||||
|
|
||||||
|
var MARKER = 'YOUR CHANGES WILL BE ERASED!';
|
||||||
|
var SIGNING_PROPERTIES = '-signing.properties';
|
||||||
|
var TEMPLATE =
|
||||||
|
'# This file is automatically generated.\n' +
|
||||||
|
'# Do not modify this file -- ' + MARKER + '\n';
|
||||||
|
|
||||||
|
function GradleBuilder (projectRoot) {
|
||||||
|
GenericBuilder.call(this, projectRoot);
|
||||||
|
|
||||||
|
this.binDirs = {gradle: this.binDirs.gradle};
|
||||||
|
}
|
||||||
|
|
||||||
|
util.inherits(GradleBuilder, GenericBuilder);
|
||||||
|
|
||||||
|
GradleBuilder.prototype.getArgs = function(cmd, opts) {
|
||||||
|
if (cmd == 'release') {
|
||||||
|
cmd = 'cdvBuildRelease';
|
||||||
|
} else if (cmd == 'debug') {
|
||||||
|
cmd = 'cdvBuildDebug';
|
||||||
|
}
|
||||||
|
var args = [cmd, '-b', path.join(this.root, 'build.gradle')];
|
||||||
|
if (opts.arch) {
|
||||||
|
args.push('-PcdvBuildArch=' + opts.arch);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 10 seconds -> 6 seconds
|
||||||
|
args.push('-Dorg.gradle.daemon=true');
|
||||||
|
args.push.apply(args, opts.extraArgs);
|
||||||
|
// Shaves another 100ms, but produces a "try at own risk" warning. Not worth it (yet):
|
||||||
|
// args.push('-Dorg.gradle.parallel=true');
|
||||||
|
return args;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Makes the project buildable, minus the gradle wrapper.
|
||||||
|
GradleBuilder.prototype.prepBuildFiles = function() {
|
||||||
|
// Update the version of build.gradle in each dependent library.
|
||||||
|
var pluginBuildGradle = path.join(this.root, 'cordova', 'lib', 'plugin-build.gradle');
|
||||||
|
var propertiesObj = this.readProjectProperties();
|
||||||
|
var subProjects = propertiesObj.libs;
|
||||||
|
for (var i = 0; i < subProjects.length; ++i) {
|
||||||
|
if (subProjects[i] !== 'CordovaLib') {
|
||||||
|
shell.cp('-f', pluginBuildGradle, path.join(this.root, subProjects[i], 'build.gradle'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var name = this.extractRealProjectNameFromManifest();
|
||||||
|
//Remove the proj.id/name- prefix from projects: https://issues.apache.org/jira/browse/CB-9149
|
||||||
|
var settingsGradlePaths = subProjects.map(function(p){
|
||||||
|
var realDir=p.replace(/[/\\]/g, ':');
|
||||||
|
var libName=realDir.replace(name+'-','');
|
||||||
|
var str='include ":'+libName+'"\n';
|
||||||
|
if(realDir.indexOf(name+'-')!==-1)
|
||||||
|
str+='project(":'+libName+'").projectDir = new File("'+p+'")\n';
|
||||||
|
return str;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Write the settings.gradle file.
|
||||||
|
fs.writeFileSync(path.join(this.root, 'settings.gradle'),
|
||||||
|
'// GENERATED FILE - DO NOT EDIT\n' +
|
||||||
|
'include ":"\n' + settingsGradlePaths.join(''));
|
||||||
|
// Update dependencies within build.gradle.
|
||||||
|
var buildGradle = fs.readFileSync(path.join(this.root, 'build.gradle'), 'utf8');
|
||||||
|
var depsList = '';
|
||||||
|
subProjects.forEach(function(p) {
|
||||||
|
var libName=p.replace(/[/\\]/g, ':').replace(name+'-','');
|
||||||
|
depsList += ' debugCompile project(path: "' + libName + '", configuration: "debug")\n';
|
||||||
|
depsList += ' releaseCompile project(path: "' + libName + '", configuration: "release")\n';
|
||||||
|
});
|
||||||
|
// For why we do this mapping: https://issues.apache.org/jira/browse/CB-8390
|
||||||
|
var SYSTEM_LIBRARY_MAPPINGS = [
|
||||||
|
[/^\/?extras\/android\/support\/(.*)$/, 'com.android.support:support-$1:+'],
|
||||||
|
[/^\/?google\/google_play_services\/libproject\/google-play-services_lib\/?$/, 'com.google.android.gms:play-services:+']
|
||||||
|
];
|
||||||
|
propertiesObj.systemLibs.forEach(function(p) {
|
||||||
|
var mavenRef;
|
||||||
|
// It's already in gradle form if it has two ':'s
|
||||||
|
if (/:.*:/.exec(p)) {
|
||||||
|
mavenRef = p;
|
||||||
|
} else {
|
||||||
|
for (var i = 0; i < SYSTEM_LIBRARY_MAPPINGS.length; ++i) {
|
||||||
|
var pair = SYSTEM_LIBRARY_MAPPINGS[i];
|
||||||
|
if (pair[0].exec(p)) {
|
||||||
|
mavenRef = p.replace(pair[0], pair[1]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!mavenRef) {
|
||||||
|
throw new CordovaError('Unsupported system library (does not work with gradle): ' + p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
depsList += ' compile "' + mavenRef + '"\n';
|
||||||
|
});
|
||||||
|
buildGradle = buildGradle.replace(/(SUB-PROJECT DEPENDENCIES START)[\s\S]*(\/\/ SUB-PROJECT DEPENDENCIES END)/, '$1\n' + depsList + ' $2');
|
||||||
|
var includeList = '';
|
||||||
|
propertiesObj.gradleIncludes.forEach(function(includePath) {
|
||||||
|
includeList += 'apply from: "' + includePath + '"\n';
|
||||||
|
});
|
||||||
|
buildGradle = buildGradle.replace(/(PLUGIN GRADLE EXTENSIONS START)[\s\S]*(\/\/ PLUGIN GRADLE EXTENSIONS END)/, '$1\n' + includeList + '$2');
|
||||||
|
fs.writeFileSync(path.join(this.root, 'build.gradle'), buildGradle);
|
||||||
|
};
|
||||||
|
|
||||||
|
GradleBuilder.prototype.prepEnv = function(opts) {
|
||||||
|
var self = this;
|
||||||
|
return check_reqs.check_gradle()
|
||||||
|
.then(function() {
|
||||||
|
return self.prepBuildFiles();
|
||||||
|
}).then(function() {
|
||||||
|
// Copy the gradle wrapper on each build so that:
|
||||||
|
// A) we don't require the Android SDK at project creation time, and
|
||||||
|
// B) we always use the SDK's latest version of it.
|
||||||
|
// check_reqs ensures that this is set.
|
||||||
|
/*jshint -W069 */
|
||||||
|
var sdkDir = process.env['ANDROID_HOME'];
|
||||||
|
/*jshint +W069 */
|
||||||
|
var wrapperDir = path.join(sdkDir, 'tools', 'templates', 'gradle', 'wrapper');
|
||||||
|
if (process.platform == 'win32') {
|
||||||
|
shell.rm('-f', path.join(self.root, 'gradlew.bat'));
|
||||||
|
shell.cp(path.join(wrapperDir, 'gradlew.bat'), self.root);
|
||||||
|
} else {
|
||||||
|
shell.rm('-f', path.join(self.root, 'gradlew'));
|
||||||
|
shell.cp(path.join(wrapperDir, 'gradlew'), self.root);
|
||||||
|
}
|
||||||
|
shell.rm('-rf', path.join(self.root, 'gradle', 'wrapper'));
|
||||||
|
shell.mkdir('-p', path.join(self.root, 'gradle'));
|
||||||
|
shell.cp('-r', path.join(wrapperDir, 'gradle', 'wrapper'), path.join(self.root, 'gradle'));
|
||||||
|
|
||||||
|
// If the gradle distribution URL is set, make sure it points to version we want.
|
||||||
|
// If it's not set, do nothing, assuming that we're using a future version of gradle that we don't want to mess with.
|
||||||
|
// For some reason, using ^ and $ don't work. This does the job, though.
|
||||||
|
var distributionUrlRegex = /distributionUrl.*zip/;
|
||||||
|
/*jshint -W069 */
|
||||||
|
var distributionUrl = process.env['CORDOVA_ANDROID_GRADLE_DISTRIBUTION_URL'] || 'http\\://services.gradle.org/distributions/gradle-2.2.1-all.zip';
|
||||||
|
/*jshint +W069 */
|
||||||
|
var gradleWrapperPropertiesPath = path.join(self.root, 'gradle', 'wrapper', 'gradle-wrapper.properties');
|
||||||
|
shell.chmod('u+w', gradleWrapperPropertiesPath);
|
||||||
|
shell.sed('-i', distributionUrlRegex, 'distributionUrl='+distributionUrl, gradleWrapperPropertiesPath);
|
||||||
|
|
||||||
|
var propertiesFile = opts.buildType + SIGNING_PROPERTIES;
|
||||||
|
var propertiesFilePath = path.join(self.root, propertiesFile);
|
||||||
|
if (opts.packageInfo) {
|
||||||
|
fs.writeFileSync(propertiesFilePath, TEMPLATE + opts.packageInfo.toProperties());
|
||||||
|
} else if (isAutoGenerated(propertiesFilePath)) {
|
||||||
|
shell.rm('-f', propertiesFilePath);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Builds the project with gradle.
|
||||||
|
* Returns a promise.
|
||||||
|
*/
|
||||||
|
GradleBuilder.prototype.build = function(opts) {
|
||||||
|
var wrapper = path.join(this.root, 'gradlew');
|
||||||
|
var args = this.getArgs(opts.buildType == 'debug' ? 'debug' : 'release', opts);
|
||||||
|
return Q().then(function() {
|
||||||
|
return spawn(wrapper, args, {stdio: 'inherit'});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
GradleBuilder.prototype.clean = function(opts) {
|
||||||
|
var builder = this;
|
||||||
|
var wrapper = path.join(this.root, 'gradlew');
|
||||||
|
var args = builder.getArgs('clean', opts);
|
||||||
|
return Q().then(function() {
|
||||||
|
return spawn(wrapper, args, {stdio: 'inherit'});
|
||||||
|
})
|
||||||
|
.then(function () {
|
||||||
|
shell.rm('-rf', path.join(builder.root, 'out'));
|
||||||
|
|
||||||
|
['debug', 'release'].forEach(function(config) {
|
||||||
|
var propertiesFilePath = path.join(builder.root, config + SIGNING_PROPERTIES);
|
||||||
|
if(isAutoGenerated(propertiesFilePath)){
|
||||||
|
shell.rm('-f', propertiesFilePath);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = GradleBuilder;
|
||||||
|
|
||||||
|
function isAutoGenerated(file) {
|
||||||
|
return fs.existsSync(file) && fs.readFileSync(file, 'utf8').indexOf(MARKER) > 0;
|
||||||
|
}
|
47
bin/templates/cordova/lib/builders/builders.js
vendored
Normal file
47
bin/templates/cordova/lib/builders/builders.js
vendored
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
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 CordovaError = require('cordova-common').CordovaError;
|
||||||
|
|
||||||
|
var knownBuilders = {
|
||||||
|
ant: 'AntBuilder',
|
||||||
|
gradle: 'GradleBuilder',
|
||||||
|
none: 'GenericBuilder'
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method that instantiates and returns a builder for specified build
|
||||||
|
* type.
|
||||||
|
*
|
||||||
|
* @param {String} builderType Builder name to construct and return. Must
|
||||||
|
* be one of 'ant', 'gradle' or 'none'
|
||||||
|
*
|
||||||
|
* @return {Builder} A builder instance for specified build type.
|
||||||
|
*/
|
||||||
|
module.exports.getBuilder = function (builderType, projectRoot) {
|
||||||
|
if (!knownBuilders[builderType])
|
||||||
|
throw new CordovaError('Builder ' + builderType + ' is not supported.');
|
||||||
|
|
||||||
|
try {
|
||||||
|
var Builder = require('./' + knownBuilders[builderType]);
|
||||||
|
return new Builder(projectRoot);
|
||||||
|
} catch (err) {
|
||||||
|
throw new CordovaError('Failed to instantiate ' + knownBuilders[builderType] + ' builder: ' + err);
|
||||||
|
}
|
||||||
|
};
|
234
bin/templates/cordova/lib/device.js
vendored
234
bin/templates/cordova/lib/device.js
vendored
@ -1,128 +1,106 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Licensed to the Apache Software Foundation (ASF) under one
|
Licensed to the Apache Software Foundation (ASF) under one
|
||||||
or more contributor license agreements. See the NOTICE file
|
or more contributor license agreements. See the NOTICE file
|
||||||
distributed with this work for additional information
|
distributed with this work for additional information
|
||||||
regarding copyright ownership. The ASF licenses this file
|
regarding copyright ownership. The ASF licenses this file
|
||||||
to you under the Apache License, Version 2.0 (the
|
to you under the Apache License, Version 2.0 (the
|
||||||
"License"); you may not use this file except in compliance
|
"License"); you may not use this file except in compliance
|
||||||
with the License. You may obtain a copy of the License at
|
with the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing,
|
Unless required by applicable law or agreed to in writing,
|
||||||
software distributed under the License is distributed on an
|
software distributed under the License is distributed on an
|
||||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
KIND, either express or implied. See the License for the
|
KIND, either express or implied. See the License for the
|
||||||
specific language governing permissions and limitations
|
specific language governing permissions and limitations
|
||||||
under the License.
|
under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var exec = require('./exec'),
|
var Q = require('q'),
|
||||||
Q = require('q'),
|
build = require('./build');
|
||||||
os = require('os'),
|
var path = require('path');
|
||||||
build = require('./build'),
|
var Adb = require('./Adb');
|
||||||
appinfo = require('./appinfo');
|
var AndroidManifest = require('./AndroidManifest');
|
||||||
|
var spawn = require('cordova-common').superspawn.spawn;
|
||||||
/**
|
var CordovaError = require('cordova-common').CordovaError;
|
||||||
* Returns a promise for the list of the device ID's found
|
var events = require('cordova-common').events;
|
||||||
* @param lookHarder When true, try restarting adb if no devices are found.
|
|
||||||
*/
|
/**
|
||||||
module.exports.list = function(lookHarder) {
|
* Returns a promise for the list of the device ID's found
|
||||||
function helper() {
|
* @param lookHarder When true, try restarting adb if no devices are found.
|
||||||
return exec('adb devices', os.tmpdir())
|
*/
|
||||||
.then(function(output) {
|
module.exports.list = function(lookHarder) {
|
||||||
var response = output.split('\n');
|
return Adb.devices()
|
||||||
var device_list = [];
|
.then(function(list) {
|
||||||
for (var i = 1; i < response.length; i++) {
|
if (list.length === 0 && lookHarder) {
|
||||||
if (response[i].match(/\w+\tdevice/) && !response[i].match(/emulator/)) {
|
// adb kill-server doesn't seem to do the trick.
|
||||||
device_list.push(response[i].replace(/\tdevice/, '').replace('\r', ''));
|
// Could probably find a x-platform version of killall, but I'm not actually
|
||||||
}
|
// sure that this scenario even happens on non-OSX machines.
|
||||||
}
|
return spawn('killall', ['adb'])
|
||||||
return device_list;
|
.then(function() {
|
||||||
});
|
events.emit('verbose', 'Restarting adb to see if more devices are detected.');
|
||||||
}
|
return Adb.devices();
|
||||||
return helper()
|
}, function() {
|
||||||
.then(function(list) {
|
// For non-killall OS's.
|
||||||
if (list.length === 0 && lookHarder) {
|
return list;
|
||||||
// adb kill-server doesn't seem to do the trick.
|
});
|
||||||
// Could probably find a x-platform version of killall, but I'm not actually
|
}
|
||||||
// sure that this scenario even happens on non-OSX machines.
|
return list;
|
||||||
return exec('killall adb')
|
});
|
||||||
.then(function() {
|
};
|
||||||
console.log('Restarting adb to see if more devices are detected.');
|
|
||||||
return helper();
|
module.exports.resolveTarget = function(target) {
|
||||||
}, function() {
|
return this.list(true)
|
||||||
// For non-killall OS's.
|
.then(function(device_list) {
|
||||||
return list;
|
if (!device_list || !device_list.length) {
|
||||||
});
|
return Q.reject(new CordovaError('Failed to deploy to device, no devices found.'));
|
||||||
}
|
}
|
||||||
return list;
|
// default device
|
||||||
});
|
target = target || device_list[0];
|
||||||
};
|
|
||||||
|
if (device_list.indexOf(target) < 0) {
|
||||||
module.exports.resolveTarget = function(target) {
|
return Q.reject('ERROR: Unable to find target \'' + target + '\'.');
|
||||||
return this.list(true)
|
}
|
||||||
.then(function(device_list) {
|
|
||||||
if (!device_list || !device_list.length) {
|
return build.detectArchitecture(target)
|
||||||
return Q.reject('ERROR: Failed to deploy to device, no devices found.');
|
.then(function(arch) {
|
||||||
}
|
return { target: target, arch: arch, isEmulator: false };
|
||||||
// default device
|
});
|
||||||
target = target || device_list[0];
|
});
|
||||||
|
};
|
||||||
if (device_list.indexOf(target) < 0) {
|
|
||||||
return Q.reject('ERROR: Unable to find target \'' + target + '\'.');
|
/*
|
||||||
}
|
* Installs a previously built application on the device
|
||||||
|
* and launches it.
|
||||||
return build.detectArchitecture(target)
|
* Returns a promise.
|
||||||
.then(function(arch) {
|
*/
|
||||||
return { target: target, arch: arch, isEmulator: false };
|
module.exports.install = function(target, buildResults) {
|
||||||
});
|
return Q().then(function() {
|
||||||
});
|
if (target && typeof target == 'object') {
|
||||||
};
|
return target;
|
||||||
|
}
|
||||||
/*
|
return module.exports.resolveTarget(target);
|
||||||
* Installs a previously built application on the device
|
}).then(function(resolvedTarget) {
|
||||||
* and launches it.
|
var apk_path = build.findBestApkForArchitecture(buildResults, resolvedTarget.arch);
|
||||||
* Returns a promise.
|
var manifest = new AndroidManifest(path.join(__dirname, '../../AndroidManifest.xml'));
|
||||||
*/
|
var pkgName = manifest.getPackageId();
|
||||||
module.exports.install = function(target, buildResults) {
|
var launchName = pkgName + '/.' + manifest.getActivity().getName();
|
||||||
return Q().then(function() {
|
events.emit('log', 'Using apk: ' + apk_path);
|
||||||
if (target && typeof target == 'object') {
|
// This promise is always resolved, even if 'adb uninstall' fails to uninstall app
|
||||||
return target;
|
// or the app doesn't installed at all, so no error catching needed.
|
||||||
}
|
return Adb.uninstall(resolvedTarget.target, pkgName)
|
||||||
return module.exports.resolveTarget(target);
|
.then(function() {
|
||||||
}).then(function(resolvedTarget) {
|
return Adb.install(resolvedTarget.target, apk_path, {replace: true});
|
||||||
var apk_path = build.findBestApkForArchitecture(buildResults, resolvedTarget.arch);
|
}).then(function() {
|
||||||
var launchName = appinfo.getActivityName();
|
//unlock screen
|
||||||
var pkgName = appinfo.getPackageName();
|
return Adb.shell(resolvedTarget.target, 'input keyevent 82');
|
||||||
console.log('Using apk: ' + apk_path);
|
}).then(function() {
|
||||||
console.log('Uninstalling ' + pkgName + ' from device...');
|
return Adb.start(resolvedTarget.target, launchName);
|
||||||
// This promise is always resolved, even if 'adb uninstall' fails to uninstall app
|
}).then(function() {
|
||||||
// or the app doesn't installed at all, so no error catching needed.
|
events.emit('log', 'LAUNCH SUCCESS');
|
||||||
return exec('adb -s ' + resolvedTarget.target + ' uninstall ' + pkgName, os.tmpdir())
|
});
|
||||||
.then(function() {
|
});
|
||||||
console.log('Installing app on device...');
|
};
|
||||||
var cmd = 'adb -s ' + resolvedTarget.target + ' install -r "' + apk_path + '"';
|
|
||||||
return exec(cmd, os.tmpdir());
|
|
||||||
})
|
|
||||||
.then(function(output) {
|
|
||||||
if (output.match(/Failure/)) return Q.reject('ERROR: Failed to install apk to device: ' + output);
|
|
||||||
|
|
||||||
//unlock screen
|
|
||||||
var cmd = 'adb -s ' + resolvedTarget.target + ' shell input keyevent 82';
|
|
||||||
return exec(cmd, os.tmpdir());
|
|
||||||
}, function(err) { return Q.reject('ERROR: Failed to install apk to device: ' + err); })
|
|
||||||
.then(function() {
|
|
||||||
// launch the application
|
|
||||||
console.log('Launching application...');
|
|
||||||
var cmd = 'adb -s ' + resolvedTarget.target + ' shell am start -W -a android.intent.action.MAIN -n ' + launchName;
|
|
||||||
return exec(cmd, os.tmpdir());
|
|
||||||
}).then(function() {
|
|
||||||
console.log('LAUNCH SUCCESS');
|
|
||||||
}, function(err) {
|
|
||||||
return Q.reject('ERROR: Failed to launch application on device: ' + err);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
752
bin/templates/cordova/lib/emulator.js
vendored
752
bin/templates/cordova/lib/emulator.js
vendored
@ -1,380 +1,372 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Licensed to the Apache Software Foundation (ASF) under one
|
Licensed to the Apache Software Foundation (ASF) under one
|
||||||
or more contributor license agreements. See the NOTICE file
|
or more contributor license agreements. See the NOTICE file
|
||||||
distributed with this work for additional information
|
distributed with this work for additional information
|
||||||
regarding copyright ownership. The ASF licenses this file
|
regarding copyright ownership. The ASF licenses this file
|
||||||
to you under the Apache License, Version 2.0 (the
|
to you under the Apache License, Version 2.0 (the
|
||||||
"License"); you may not use this file except in compliance
|
"License"); you may not use this file except in compliance
|
||||||
with the License. You may obtain a copy of the License at
|
with the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing,
|
Unless required by applicable law or agreed to in writing,
|
||||||
software distributed under the License is distributed on an
|
software distributed under the License is distributed on an
|
||||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
KIND, either express or implied. See the License for the
|
KIND, either express or implied. See the License for the
|
||||||
specific language governing permissions and limitations
|
specific language governing permissions and limitations
|
||||||
under the License.
|
under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* jshint sub:true */
|
/* jshint sub:true */
|
||||||
|
|
||||||
var exec = require('./exec');
|
var retry = require('./retry');
|
||||||
var appinfo = require('./appinfo');
|
var build = require('./build');
|
||||||
var retry = require('./retry');
|
var check_reqs = require('./check_reqs');
|
||||||
var build = require('./build');
|
var path = require('path');
|
||||||
var check_reqs = require('./check_reqs');
|
var Adb = require('./Adb');
|
||||||
|
var AndroidManifest = require('./AndroidManifest');
|
||||||
var Q = require('q');
|
var events = require('cordova-common').events;
|
||||||
var os = require('os');
|
var spawn = require('cordova-common').superspawn.spawn;
|
||||||
var child_process = require('child_process');
|
var CordovaError = require('cordova-common').CordovaError;
|
||||||
|
|
||||||
// constants
|
var Q = require('q');
|
||||||
var ONE_SECOND = 1000; // in milliseconds
|
var os = require('os');
|
||||||
var ONE_MINUTE = 60 * ONE_SECOND; // in milliseconds
|
var child_process = require('child_process');
|
||||||
var INSTALL_COMMAND_TIMEOUT = 5 * ONE_MINUTE; // in milliseconds
|
|
||||||
var NUM_INSTALL_RETRIES = 3;
|
// constants
|
||||||
var EXEC_KILL_SIGNAL = 'SIGKILL';
|
var ONE_SECOND = 1000; // in milliseconds
|
||||||
|
var ONE_MINUTE = 60 * ONE_SECOND; // in milliseconds
|
||||||
/**
|
var INSTALL_COMMAND_TIMEOUT = 5 * ONE_MINUTE; // in milliseconds
|
||||||
* Returns a Promise for a list of emulator images in the form of objects
|
var NUM_INSTALL_RETRIES = 3;
|
||||||
* {
|
var EXEC_KILL_SIGNAL = 'SIGKILL';
|
||||||
name : <emulator_name>,
|
|
||||||
path : <path_to_emulator_image>,
|
/**
|
||||||
target : <api_target>,
|
* Returns a Promise for a list of emulator images in the form of objects
|
||||||
abi : <cpu>,
|
* {
|
||||||
skin : <skin>
|
name : <emulator_name>,
|
||||||
}
|
path : <path_to_emulator_image>,
|
||||||
*/
|
target : <api_target>,
|
||||||
module.exports.list_images = function() {
|
abi : <cpu>,
|
||||||
return exec('android list avds')
|
skin : <skin>
|
||||||
.then(function(output) {
|
}
|
||||||
var response = output.split('\n');
|
*/
|
||||||
var emulator_list = [];
|
module.exports.list_images = function() {
|
||||||
for (var i = 1; i < response.length; i++) {
|
return spawn('android', ['list', 'avds'])
|
||||||
// To return more detailed information use img_obj
|
.then(function(output) {
|
||||||
var img_obj = {};
|
var response = output.split('\n');
|
||||||
if (response[i].match(/Name:\s/)) {
|
var emulator_list = [];
|
||||||
img_obj['name'] = response[i].split('Name: ')[1].replace('\r', '');
|
for (var i = 1; i < response.length; i++) {
|
||||||
if (response[i + 1].match(/Path:\s/)) {
|
// To return more detailed information use img_obj
|
||||||
i++;
|
var img_obj = {};
|
||||||
img_obj['path'] = response[i].split('Path: ')[1].replace('\r', '');
|
if (response[i].match(/Name:\s/)) {
|
||||||
}
|
img_obj['name'] = response[i].split('Name: ')[1].replace('\r', '');
|
||||||
if (response[i + 1].match(/\(API\slevel\s/)) {
|
if (response[i + 1].match(/Path:\s/)) {
|
||||||
i++;
|
i++;
|
||||||
img_obj['target'] = response[i].replace('\r', '');
|
img_obj['path'] = response[i].split('Path: ')[1].replace('\r', '');
|
||||||
}
|
}
|
||||||
if (response[i + 1].match(/ABI:\s/)) {
|
if (response[i + 1].match(/\(API\slevel\s/)) {
|
||||||
i++;
|
i++;
|
||||||
img_obj['abi'] = response[i].split('ABI: ')[1].replace('\r', '');
|
img_obj['target'] = response[i].replace('\r', '');
|
||||||
}
|
}
|
||||||
if (response[i + 1].match(/Skin:\s/)) {
|
if (response[i + 1].match(/ABI:\s/)) {
|
||||||
i++;
|
i++;
|
||||||
img_obj['skin'] = response[i].split('Skin: ')[1].replace('\r', '');
|
img_obj['abi'] = response[i].split('ABI: ')[1].replace('\r', '');
|
||||||
}
|
}
|
||||||
|
if (response[i + 1].match(/Skin:\s/)) {
|
||||||
emulator_list.push(img_obj);
|
i++;
|
||||||
}
|
img_obj['skin'] = response[i].split('Skin: ')[1].replace('\r', '');
|
||||||
/* To just return a list of names use this
|
}
|
||||||
if (response[i].match(/Name:\s/)) {
|
|
||||||
emulator_list.push(response[i].split('Name: ')[1].replace('\r', '');
|
emulator_list.push(img_obj);
|
||||||
}*/
|
}
|
||||||
|
/* To just return a list of names use this
|
||||||
}
|
if (response[i].match(/Name:\s/)) {
|
||||||
return emulator_list;
|
emulator_list.push(response[i].split('Name: ')[1].replace('\r', '');
|
||||||
});
|
}*/
|
||||||
};
|
|
||||||
|
}
|
||||||
/**
|
return emulator_list;
|
||||||
* Will return the closest avd to the projects target
|
});
|
||||||
* or undefined if no avds exist.
|
};
|
||||||
* Returns a promise.
|
|
||||||
*/
|
/**
|
||||||
module.exports.best_image = function() {
|
* Will return the closest avd to the projects target
|
||||||
var project_target = check_reqs.get_target().replace('android-', '');
|
* or undefined if no avds exist.
|
||||||
return this.list_images()
|
* Returns a promise.
|
||||||
.then(function(images) {
|
*/
|
||||||
var closest = 9999;
|
module.exports.best_image = function() {
|
||||||
var best = images[0];
|
return this.list_images()
|
||||||
for (var i in images) {
|
.then(function(images) {
|
||||||
var target = images[i].target;
|
// Just return undefined if there is no images
|
||||||
if(target) {
|
if (images.length === 0) return;
|
||||||
var num = target.split('(API level ')[1].replace(')', '');
|
|
||||||
if (num == project_target) {
|
var closest = 9999;
|
||||||
return images[i];
|
var best = images[0];
|
||||||
} else if (project_target - num < closest && project_target > num) {
|
var project_target = check_reqs.get_target().replace('android-', '');
|
||||||
closest = project_target - num;
|
for (var i in images) {
|
||||||
best = images[i];
|
var target = images[i].target;
|
||||||
}
|
if(target) {
|
||||||
}
|
var num = target.split('(API level ')[1].replace(')', '');
|
||||||
}
|
if (num == project_target) {
|
||||||
return best;
|
return images[i];
|
||||||
});
|
} else if (project_target - num < closest && project_target > num) {
|
||||||
};
|
closest = project_target - num;
|
||||||
|
best = images[i];
|
||||||
// Returns a promise.
|
}
|
||||||
module.exports.list_started = function() {
|
}
|
||||||
return exec('adb devices', os.tmpdir())
|
}
|
||||||
.then(function(output) {
|
return best;
|
||||||
var response = output.split('\n');
|
});
|
||||||
var started_emulator_list = [];
|
};
|
||||||
for (var i = 1; i < response.length; i++) {
|
|
||||||
if (response[i].match(/device/) && response[i].match(/emulator/)) {
|
// Returns a promise.
|
||||||
started_emulator_list.push(response[i].replace(/\tdevice/, '').replace('\r', ''));
|
module.exports.list_started = function() {
|
||||||
}
|
return Adb.devices({emulators: true});
|
||||||
}
|
};
|
||||||
return started_emulator_list;
|
|
||||||
});
|
// Returns a promise.
|
||||||
};
|
module.exports.list_targets = function() {
|
||||||
|
return spawn('android', ['list', 'targets'], {cwd: os.tmpdir()})
|
||||||
// Returns a promise.
|
.then(function(output) {
|
||||||
module.exports.list_targets = function() {
|
var target_out = output.split('\n');
|
||||||
return exec('android list targets', os.tmpdir())
|
var targets = [];
|
||||||
.then(function(output) {
|
for (var i = target_out.length; i >= 0; i--) {
|
||||||
var target_out = output.split('\n');
|
if(target_out[i].match(/id:/)) {
|
||||||
var targets = [];
|
targets.push(targets[i].split(' ')[1]);
|
||||||
for (var i = target_out.length; i >= 0; i--) {
|
}
|
||||||
if(target_out[i].match(/id:/)) {
|
}
|
||||||
targets.push(targets[i].split(' ')[1]);
|
return targets;
|
||||||
}
|
});
|
||||||
}
|
};
|
||||||
return targets;
|
|
||||||
});
|
/*
|
||||||
};
|
* Starts an emulator with the given ID,
|
||||||
|
* and returns the started ID of that emulator.
|
||||||
/*
|
* If no ID is given it will use the first image available,
|
||||||
* Starts an emulator with the given ID,
|
* if no image is available it will error out (maybe create one?).
|
||||||
* and returns the started ID of that emulator.
|
*
|
||||||
* If no ID is given it will use the first image available,
|
* Returns a promise.
|
||||||
* if no image is available it will error out (maybe create one?).
|
*/
|
||||||
*
|
module.exports.start = function(emulator_ID) {
|
||||||
* Returns a promise.
|
var self = this;
|
||||||
*/
|
|
||||||
module.exports.start = function(emulator_ID) {
|
return Q().then(function() {
|
||||||
var self = this;
|
if (emulator_ID) return Q(emulator_ID);
|
||||||
var now = new Date();
|
|
||||||
var uuid = 'cordova_emulator_' + now.getTime();
|
return self.best_image()
|
||||||
var emulator_id;
|
.then(function(best) {
|
||||||
|
if (best && best.name) {
|
||||||
return Q().then(function(list) {
|
events.emit('warn', 'No emulator specified, defaulting to ' + best.name);
|
||||||
if (!emulator_ID) {
|
return best.name;
|
||||||
return self.list_images()
|
}
|
||||||
.then(function(emulator_list) {
|
|
||||||
if (emulator_list.length > 0) {
|
var androidCmd = check_reqs.getAbsoluteAndroidCmd();
|
||||||
return self.best_image()
|
return Q.reject(new CordovaError('No emulator images (avds) found.\n' +
|
||||||
.then(function(best) {
|
'1. Download desired System Image by running: ' + androidCmd + ' sdk\n' +
|
||||||
emulator_ID = best.name;
|
'2. Create an AVD by running: ' + androidCmd + ' avd\n' +
|
||||||
console.log('WARNING : no emulator specified, defaulting to ' + emulator_ID);
|
'HINT: For a faster emulator, use an Intel System Image and install the HAXM device driver\n'));
|
||||||
return emulator_ID;
|
});
|
||||||
});
|
}).then(function(emulatorId) {
|
||||||
} else {
|
var uuid = 'cordova_emulator_' + new Date().getTime();
|
||||||
var androidCmd = check_reqs.getAbsoluteAndroidCmd();
|
var uuidProp = 'emu.uuid=' + uuid;
|
||||||
return Q.reject('ERROR : No emulator images (avds) found.\n' +
|
var args = ['-avd', emulatorId, '-prop', uuidProp];
|
||||||
'1. Download desired System Image by running: ' + androidCmd + ' sdk\n' +
|
// Don't wait for it to finish, since the emulator will probably keep running for a long time.
|
||||||
'2. Create an AVD by running: ' + androidCmd + ' avd\n' +
|
child_process
|
||||||
'HINT: For a faster emulator, use an Intel System Image and install the HAXM device driver\n');
|
.spawn('emulator', args, { stdio: 'inherit', detached: true })
|
||||||
}
|
.unref();
|
||||||
});
|
|
||||||
} else {
|
// wait for emulator to start
|
||||||
return Q(emulator_ID);
|
events.emit('log', 'Waiting for emulator...');
|
||||||
}
|
return self.wait_for_emulator(uuid);
|
||||||
}).then(function() {
|
}).then(function(emulatorId) {
|
||||||
var cmd = 'emulator';
|
if (!emulatorId)
|
||||||
var uuidProp = 'emu.uuid=' + uuid;
|
return Q.reject(new CordovaError('Failed to start emulator'));
|
||||||
var args = ['-avd', emulator_ID, '-prop', uuidProp];
|
|
||||||
var proc = child_process.spawn(cmd, args, { stdio: 'inherit', detached: true });
|
//wait for emulator to boot up
|
||||||
proc.unref(); // Don't wait for it to finish, since the emulator will probably keep running for a long time.
|
process.stdout.write('Booting up emulator (this may take a while)...');
|
||||||
}).then(function() {
|
return self.wait_for_boot(emulatorId)
|
||||||
// wait for emulator to start
|
.then(function() {
|
||||||
console.log('Waiting for emulator...');
|
events.emit('log','BOOT COMPLETE');
|
||||||
return self.wait_for_emulator(uuid);
|
//unlock screen
|
||||||
}).then(function(emId) {
|
return Adb.shell(emulatorId, 'input keyevent 82');
|
||||||
emulator_id = emId;
|
}).then(function() {
|
||||||
if (!emulator_id) return Q.reject('ERROR : Failed to start emulator');
|
//return the new emulator id for the started emulators
|
||||||
|
return emulatorId;
|
||||||
//wait for emulator to boot up
|
});
|
||||||
process.stdout.write('Booting up emulator (this may take a while)...');
|
});
|
||||||
return self.wait_for_boot(emulator_id);
|
};
|
||||||
}).then(function() {
|
|
||||||
console.log('BOOT COMPLETE');
|
/*
|
||||||
|
* Waits for an emulator with given uuid to apear on the started-emulator list.
|
||||||
//unlock screen
|
* Returns a promise with this emulator's ID.
|
||||||
return exec('adb -s ' + emulator_id + ' shell input keyevent 82', os.tmpdir());
|
*/
|
||||||
}).then(function() {
|
module.exports.wait_for_emulator = function(uuid) {
|
||||||
//return the new emulator id for the started emulators
|
var self = this;
|
||||||
return emulator_id;
|
return self.list_started()
|
||||||
});
|
.then(function(new_started) {
|
||||||
};
|
var emulator_id = null;
|
||||||
|
var promises = [];
|
||||||
/*
|
|
||||||
* Waits for an emulator with given uuid to apear on the started-emulator list.
|
new_started.forEach(function (emulator) {
|
||||||
* Returns a promise with this emulator's ID.
|
promises.push(
|
||||||
*/
|
Adb.shell(emulator, 'getprop emu.uuid')
|
||||||
module.exports.wait_for_emulator = function(uuid) {
|
.then(function (output) {
|
||||||
var self = this;
|
if (output.indexOf(uuid) >= 0) {
|
||||||
return self.list_started()
|
emulator_id = emulator;
|
||||||
.then(function(new_started) {
|
}
|
||||||
var emulator_id = null;
|
})
|
||||||
var promises = [];
|
);
|
||||||
|
});
|
||||||
new_started.forEach(function (emulator) {
|
|
||||||
promises.push(exec('adb -s ' + emulator + ' shell getprop emu.uuid', os.tmpdir())
|
return Q.all(promises).then(function () {
|
||||||
.then(function (output) {
|
return emulator_id || self.wait_for_emulator(uuid);
|
||||||
if (output.indexOf(uuid) >= 0) {
|
});
|
||||||
emulator_id = emulator;
|
});
|
||||||
}
|
};
|
||||||
})
|
|
||||||
);
|
/*
|
||||||
});
|
* Waits for the core android process of the emulator to start
|
||||||
|
*/
|
||||||
return Q.all(promises).then(function () {
|
module.exports.wait_for_boot = function(emulator_id) {
|
||||||
return emulator_id || self.wait_for_emulator(uuid);
|
var self = this;
|
||||||
});
|
return Adb.shell(emulator_id, 'ps')
|
||||||
});
|
.then(function(output) {
|
||||||
};
|
if (output.match(/android\.process\.acore/)) {
|
||||||
|
return;
|
||||||
/*
|
} else {
|
||||||
* Waits for the core android process of the emulator to start
|
process.stdout.write('.');
|
||||||
*/
|
return Q.delay(3000).then(function() {
|
||||||
module.exports.wait_for_boot = function(emulator_id) {
|
return self.wait_for_boot(emulator_id);
|
||||||
var self = this;
|
});
|
||||||
return exec('adb -s ' + emulator_id + ' shell ps', os.tmpdir())
|
}
|
||||||
.then(function(output) {
|
});
|
||||||
if (output.match(/android\.process\.acore/)) {
|
};
|
||||||
return;
|
|
||||||
} else {
|
/*
|
||||||
process.stdout.write('.');
|
* Create avd
|
||||||
return Q.delay(3000).then(function() {
|
* TODO : Enter the stdin input required to complete the creation of an avd.
|
||||||
return self.wait_for_boot(emulator_id);
|
* Returns a promise.
|
||||||
});
|
*/
|
||||||
}
|
module.exports.create_image = function(name, target) {
|
||||||
});
|
console.log('Creating avd named ' + name);
|
||||||
};
|
if (target) {
|
||||||
|
return spawn('android', ['create', 'avd', '--name', name, '--target', target])
|
||||||
/*
|
.then(null, function(error) {
|
||||||
* Create avd
|
console.error('ERROR : Failed to create emulator image : ');
|
||||||
* TODO : Enter the stdin input required to complete the creation of an avd.
|
console.error(' Do you have the latest android targets including ' + target + '?');
|
||||||
* Returns a promise.
|
console.error(error);
|
||||||
*/
|
});
|
||||||
module.exports.create_image = function(name, target) {
|
} else {
|
||||||
console.log('Creating avd named ' + name);
|
console.log('WARNING : Project target not found, creating avd with a different target but the project may fail to install.');
|
||||||
if (target) {
|
return spawn('android', ['create', 'avd', '--name', name, '--target', this.list_targets()[0]])
|
||||||
return exec('android create avd --name ' + name + ' --target ' + target)
|
.then(function() {
|
||||||
.then(null, function(error) {
|
// TODO: This seems like another error case, even though it always happens.
|
||||||
console.error('ERROR : Failed to create emulator image : ');
|
console.error('ERROR : Unable to create an avd emulator, no targets found.');
|
||||||
console.error(' Do you have the latest android targets including ' + target + '?');
|
console.error('Please insure you have targets available by running the "android" command');
|
||||||
console.error(error);
|
return Q.reject();
|
||||||
});
|
}, function(error) {
|
||||||
} else {
|
console.error('ERROR : Failed to create emulator image : ');
|
||||||
console.log('WARNING : Project target not found, creating avd with a different target but the project may fail to install.');
|
console.error(error);
|
||||||
return exec('android create avd --name ' + name + ' --target ' + this.list_targets()[0])
|
});
|
||||||
.then(function() {
|
}
|
||||||
// TODO: This seems like another error case, even though it always happens.
|
};
|
||||||
console.error('ERROR : Unable to create an avd emulator, no targets found.');
|
|
||||||
console.error('Please insure you have targets available by running the "android" command');
|
module.exports.resolveTarget = function(target) {
|
||||||
return Q.reject();
|
return this.list_started()
|
||||||
}, function(error) {
|
.then(function(emulator_list) {
|
||||||
console.error('ERROR : Failed to create emulator image : ');
|
if (emulator_list.length < 1) {
|
||||||
console.error(error);
|
return Q.reject('No started emulators found, please start an emultor before deploying your project.');
|
||||||
});
|
}
|
||||||
}
|
|
||||||
};
|
// default emulator
|
||||||
|
target = target || emulator_list[0];
|
||||||
module.exports.resolveTarget = function(target) {
|
if (emulator_list.indexOf(target) < 0) {
|
||||||
return this.list_started()
|
return Q.reject('Unable to find target \'' + target + '\'. Failed to deploy to emulator.');
|
||||||
.then(function(emulator_list) {
|
}
|
||||||
if (emulator_list.length < 1) {
|
|
||||||
return Q.reject('No started emulators found, please start an emultor before deploying your project.');
|
return build.detectArchitecture(target)
|
||||||
}
|
.then(function(arch) {
|
||||||
|
return {target:target, arch:arch, isEmulator:true};
|
||||||
// default emulator
|
});
|
||||||
target = target || emulator_list[0];
|
});
|
||||||
if (emulator_list.indexOf(target) < 0) {
|
};
|
||||||
return Q.reject('Unable to find target \'' + target + '\'. Failed to deploy to emulator.');
|
|
||||||
}
|
/*
|
||||||
|
* Installs a previously built application on the emulator and launches it.
|
||||||
return build.detectArchitecture(target)
|
* If no target is specified, then it picks one.
|
||||||
.then(function(arch) {
|
* If no started emulators are found, error out.
|
||||||
return {target:target, arch:arch, isEmulator:true};
|
* Returns a promise.
|
||||||
});
|
*/
|
||||||
});
|
module.exports.install = function(givenTarget, buildResults) {
|
||||||
};
|
|
||||||
|
var target;
|
||||||
/*
|
var manifest = new AndroidManifest(path.join(__dirname, '../../AndroidManifest.xml'));
|
||||||
* Installs a previously built application on the emulator and launches it.
|
var pkgName = manifest.getPackageId();
|
||||||
* If no target is specified, then it picks one.
|
|
||||||
* If no started emulators are found, error out.
|
// resolve the target emulator
|
||||||
* Returns a promise.
|
return Q().then(function () {
|
||||||
*/
|
if (givenTarget && typeof givenTarget == 'object') {
|
||||||
module.exports.install = function(givenTarget, buildResults) {
|
return givenTarget;
|
||||||
|
} else {
|
||||||
var target;
|
return module.exports.resolveTarget(givenTarget);
|
||||||
|
}
|
||||||
// resolve the target emulator
|
|
||||||
return Q().then(function () {
|
// set the resolved target
|
||||||
if (givenTarget && typeof givenTarget == 'object') {
|
}).then(function (resolvedTarget) {
|
||||||
return givenTarget;
|
target = resolvedTarget;
|
||||||
} else {
|
|
||||||
return module.exports.resolveTarget(givenTarget);
|
// install the app
|
||||||
}
|
}).then(function () {
|
||||||
|
// This promise is always resolved, even if 'adb uninstall' fails to uninstall app
|
||||||
// set the resolved target
|
// or the app doesn't installed at all, so no error catching needed.
|
||||||
}).then(function (resolvedTarget) {
|
return Adb.uninstall(target.target, pkgName)
|
||||||
target = resolvedTarget;
|
.then(function() {
|
||||||
|
|
||||||
// install the app
|
var apk_path = build.findBestApkForArchitecture(buildResults, target.arch);
|
||||||
}).then(function () {
|
var execOptions = {
|
||||||
var pkgName = appinfo.getPackageName();
|
cwd: os.tmpdir(),
|
||||||
console.log('Uninstalling ' + pkgName + ' from emulator...');
|
timeout: INSTALL_COMMAND_TIMEOUT, // in milliseconds
|
||||||
// This promise is always resolved, even if 'adb uninstall' fails to uninstall app
|
killSignal: EXEC_KILL_SIGNAL
|
||||||
// or the app doesn't installed at all, so no error catching needed.
|
};
|
||||||
return exec('adb -s ' + target.target + ' uninstall ' + pkgName, os.tmpdir())
|
|
||||||
.then(function() {
|
events.emit('log', 'Using apk: ' + apk_path);
|
||||||
|
events.emit('verbose', 'Installing app on emulator...');
|
||||||
var apk_path = build.findBestApkForArchitecture(buildResults, target.arch);
|
|
||||||
var execOptions = {
|
function exec(command, opts) {
|
||||||
timeout: INSTALL_COMMAND_TIMEOUT, // in milliseconds
|
return Q.promise(function (resolve, reject) {
|
||||||
killSignal: EXEC_KILL_SIGNAL
|
child_process.exec(command, opts, function(err, stdout, stderr) {
|
||||||
};
|
if (err) reject(new CordovaError('Error executing "' + command + '": ' + stderr));
|
||||||
|
else resolve(stdout);
|
||||||
console.log('Installing app on emulator...');
|
});
|
||||||
console.log('Using apk: ' + apk_path);
|
});
|
||||||
|
}
|
||||||
var retriedInstall = retry.retryPromise(
|
|
||||||
NUM_INSTALL_RETRIES,
|
var retriedInstall = retry.retryPromise(
|
||||||
exec, 'adb -s ' + target.target + ' install -r "' + apk_path + '"', os.tmpdir(), execOptions
|
NUM_INSTALL_RETRIES,
|
||||||
);
|
exec, 'adb -s ' + target.target + ' install -r "' + apk_path + '"', execOptions
|
||||||
|
);
|
||||||
return retriedInstall.then(function (output) {
|
|
||||||
if (output.match(/Failure/)) {
|
return retriedInstall.then(function (output) {
|
||||||
return Q.reject('Failed to install apk to emulator: ' + output);
|
if (output.match(/Failure/)) {
|
||||||
} else {
|
return Q.reject(new CordovaError('Failed to install apk to emulator: ' + output));
|
||||||
console.log('INSTALL SUCCESS');
|
} else {
|
||||||
}
|
events.emit('log', 'INSTALL SUCCESS');
|
||||||
}, function (err) {
|
}
|
||||||
return Q.reject('Failed to install apk to emulator: ' + err);
|
}, function (err) {
|
||||||
});
|
return Q.reject(new CordovaError('Failed to install apk to emulator: ' + err));
|
||||||
});
|
});
|
||||||
// unlock screen
|
});
|
||||||
}).then(function () {
|
// unlock screen
|
||||||
|
}).then(function () {
|
||||||
console.log('Unlocking screen...');
|
|
||||||
return exec('adb -s ' + target.target + ' shell input keyevent 82', os.tmpdir());
|
events.emit('verbose', 'Unlocking screen...');
|
||||||
|
return Adb.shell(target.target, 'input keyevent 82');
|
||||||
// launch the application
|
}).then(function () {
|
||||||
}).then(function () {
|
Adb.start(target.target, pkgName + '/.' + manifest.getActivity().getName());
|
||||||
|
// report success or failure
|
||||||
console.log('Launching application...');
|
}).then(function (output) {
|
||||||
var launchName = appinfo.getActivityName();
|
events.emit('log', 'LAUNCH SUCCESS');
|
||||||
var cmd = 'adb -s ' + target.target + ' shell am start -W -a android.intent.action.MAIN -n ' + launchName;
|
});
|
||||||
return exec(cmd, os.tmpdir());
|
};
|
||||||
|
|
||||||
// report success or failure
|
|
||||||
}).then(function (output) {
|
|
||||||
console.log('LAUNCH SUCCESS');
|
|
||||||
}, function (err) {
|
|
||||||
return Q.reject('Failed to launch app on emulator: ' + err);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
68
bin/templates/cordova/lib/exec.js
vendored
68
bin/templates/cordova/lib/exec.js
vendored
@ -1,68 +0,0 @@
|
|||||||
#!/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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var child_process = require("child_process");
|
|
||||||
var Q = require("q");
|
|
||||||
|
|
||||||
// constants
|
|
||||||
var DEFAULT_MAX_BUFFER = 1024000;
|
|
||||||
|
|
||||||
// Takes a command and optional current working directory.
|
|
||||||
// Returns a promise that either resolves with the stdout, or
|
|
||||||
// rejects with an error message and the stderr.
|
|
||||||
//
|
|
||||||
// WARNING:
|
|
||||||
// opt_cwd is an artifact of an old design, and must
|
|
||||||
// be removed in the future; the correct solution is
|
|
||||||
// to pass the options object the same way that
|
|
||||||
// child_process.exec expects
|
|
||||||
//
|
|
||||||
// NOTE:
|
|
||||||
// exec documented here - https://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback
|
|
||||||
module.exports = function(cmd, opt_cwd, options) {
|
|
||||||
|
|
||||||
var d = Q.defer();
|
|
||||||
|
|
||||||
if (typeof options === "undefined") {
|
|
||||||
options = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
// override cwd to preserve old opt_cwd behavior
|
|
||||||
options.cwd = opt_cwd;
|
|
||||||
|
|
||||||
// set maxBuffer
|
|
||||||
if (typeof options.maxBuffer === "undefined") {
|
|
||||||
options.maxBuffer = DEFAULT_MAX_BUFFER;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
child_process.exec(cmd, options, function(err, stdout, stderr) {
|
|
||||||
if (err) d.reject("Error executing \"" + cmd + "\": " + stderr);
|
|
||||||
else d.resolve(stdout);
|
|
||||||
});
|
|
||||||
} catch(e) {
|
|
||||||
console.error("error caught: " + e);
|
|
||||||
d.reject(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
return d.promise;
|
|
||||||
};
|
|
||||||
|
|
252
bin/templates/cordova/lib/pluginHandlers.js
vendored
Normal file
252
bin/templates/cordova/lib/pluginHandlers.js
vendored
Normal file
@ -0,0 +1,252 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* Copyright 2013 Anis Kadri
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* jshint unused: vars */
|
||||||
|
|
||||||
|
var fs = require('fs');
|
||||||
|
var path = require('path');
|
||||||
|
var shell = require('shelljs');
|
||||||
|
var events = require('cordova-common').events;
|
||||||
|
var CordovaError = require('cordova-common').CordovaError;
|
||||||
|
|
||||||
|
var handlers = {
|
||||||
|
'source-file':{
|
||||||
|
install:function(obj, plugin, project, options) {
|
||||||
|
if (!obj.src) throw new CordovaError('<source-file> element is missing "src" attribute for plugin: ' + plugin.id);
|
||||||
|
if (!obj.targetDir) throw new CordovaError('<source-file> element is missing "target-dir" attribute for plugin: ' + plugin.id);
|
||||||
|
var dest = path.join(obj.targetDir, path.basename(obj.src));
|
||||||
|
copyNewFile(plugin.dir, obj.src, project.projectDir, dest, options && options.link);
|
||||||
|
},
|
||||||
|
uninstall:function(obj, plugin, project, options) {
|
||||||
|
var dest = path.join(obj.targetDir, path.basename(obj.src));
|
||||||
|
deleteJava(project.projectDir, dest);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'lib-file':{
|
||||||
|
install:function(obj, plugin, project, options) {
|
||||||
|
var dest = path.join('libs', path.basename(obj.src));
|
||||||
|
copyFile(plugin.dir, obj.src, project.projectDir, dest, options && options.link);
|
||||||
|
},
|
||||||
|
uninstall:function(obj, plugin, project, options) {
|
||||||
|
var dest = path.join('libs', path.basename(obj.src));
|
||||||
|
removeFile(project.projectDir, dest);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'resource-file':{
|
||||||
|
install:function(obj, plugin, project, options) {
|
||||||
|
copyFile(plugin.dir, obj.src, project.projectDir, path.normalize(obj.target), options && options.link);
|
||||||
|
},
|
||||||
|
uninstall:function(obj, plugin, project, options) {
|
||||||
|
removeFile(project.projectDir, path.normalize(obj.target));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'framework': {
|
||||||
|
install:function(obj, plugin, project, options) {
|
||||||
|
var src = obj.src;
|
||||||
|
if (!src) throw new CordovaError('src not specified in <framework> for plugin: ' + plugin.id);
|
||||||
|
|
||||||
|
events.emit('verbose', 'Installing Android library: ' + src);
|
||||||
|
var parentDir = obj.parent ? path.resolve(project.projectDir, obj.parent) : project.projectDir;
|
||||||
|
var subDir;
|
||||||
|
|
||||||
|
if (obj.custom) {
|
||||||
|
var subRelativeDir = project.getCustomSubprojectRelativeDir(plugin.id, src);
|
||||||
|
copyNewFile(plugin.dir, src, project.projectDir, subRelativeDir, options && options.link);
|
||||||
|
subDir = path.resolve(project.projectDir, subRelativeDir);
|
||||||
|
} else {
|
||||||
|
obj.type = 'sys';
|
||||||
|
subDir = src;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj.type == 'gradleReference') {
|
||||||
|
project.addGradleReference(parentDir, subDir);
|
||||||
|
} else if (obj.type == 'sys') {
|
||||||
|
project.addSystemLibrary(parentDir, subDir);
|
||||||
|
} else {
|
||||||
|
project.addSubProject(parentDir, subDir);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
uninstall:function(obj, plugin, project, options) {
|
||||||
|
var src = obj.src;
|
||||||
|
if (!src) throw new CordovaError('src not specified in <framework> for plugin: ' + plugin.id);
|
||||||
|
|
||||||
|
events.emit('verbose', 'Uninstalling Android library: ' + src);
|
||||||
|
var parentDir = obj.parent ? path.resolve(project.projectDir, obj.parent) : project.projectDir;
|
||||||
|
var subDir;
|
||||||
|
|
||||||
|
if (obj.custom) {
|
||||||
|
var subRelativeDir = project.getCustomSubprojectRelativeDir(plugin.id, src);
|
||||||
|
removeFile(project.projectDir, subRelativeDir);
|
||||||
|
subDir = path.resolve(project.projectDir, subRelativeDir);
|
||||||
|
// If it's the last framework in the plugin, remove the parent directory.
|
||||||
|
var parDir = path.dirname(subDir);
|
||||||
|
if (fs.readdirSync(parDir).length === 0) {
|
||||||
|
fs.rmdirSync(parDir);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
obj.type = 'sys';
|
||||||
|
subDir = src;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj.type == 'gradleReference') {
|
||||||
|
project.removeGradleReference(parentDir, subDir);
|
||||||
|
} else if (obj.type == 'sys') {
|
||||||
|
project.removeSystemLibrary(parentDir, subDir);
|
||||||
|
} else {
|
||||||
|
project.removeSubProject(parentDir, subDir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
asset:{
|
||||||
|
install:function(obj, plugin, project, options) {
|
||||||
|
if (!obj.src) {
|
||||||
|
throw new CordovaError('<asset> tag without required "src" attribute. plugin=' + plugin.dir);
|
||||||
|
}
|
||||||
|
if (!obj.target) {
|
||||||
|
throw new CordovaError('<asset> tag without required "target" attribute');
|
||||||
|
}
|
||||||
|
|
||||||
|
var www = options.usePlatformWww ? project.platformWww : project.www;
|
||||||
|
copyFile(plugin.dir, obj.src, www, obj.target);
|
||||||
|
},
|
||||||
|
uninstall:function(obj, plugin, project, options) {
|
||||||
|
var target = obj.target || obj.src;
|
||||||
|
|
||||||
|
if (!target) throw new CordovaError('<asset> tag without required "target" attribute');
|
||||||
|
|
||||||
|
var www = options.usePlatformWww ? project.platformWww : project.www;
|
||||||
|
removeFile(www, target);
|
||||||
|
removeFileF(path.resolve(www, 'plugins', plugin.id));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'js-module': {
|
||||||
|
install: function (obj, plugin, project, options) {
|
||||||
|
// Copy the plugin's files into the www directory.
|
||||||
|
var moduleSource = path.resolve(plugin.dir, obj.src);
|
||||||
|
var moduleName = plugin.id + '.' + (obj.name || path.parse(obj.src).name);
|
||||||
|
|
||||||
|
// Read in the file, prepend the cordova.define, and write it back out.
|
||||||
|
var scriptContent = fs.readFileSync(moduleSource, 'utf-8').replace(/^\ufeff/, ''); // Window BOM
|
||||||
|
if (moduleSource.match(/.*\.json$/)) {
|
||||||
|
scriptContent = 'module.exports = ' + scriptContent;
|
||||||
|
}
|
||||||
|
scriptContent = 'cordova.define("' + moduleName + '", function(require, exports, module) {\n' + scriptContent + '\n});\n';
|
||||||
|
|
||||||
|
var www = options.usePlatformWww ? project.platformWww : project.www;
|
||||||
|
var moduleDestination = path.resolve(www, 'plugins', plugin.id, obj.src);
|
||||||
|
shell.mkdir('-p', path.dirname(moduleDestination));
|
||||||
|
fs.writeFileSync(moduleDestination, scriptContent, 'utf-8');
|
||||||
|
},
|
||||||
|
uninstall: function (obj, plugin, project, options) {
|
||||||
|
var pluginRelativePath = path.join('plugins', plugin.id, obj.src);
|
||||||
|
var www = options.usePlatformWww ? project.platformWww : project.www;
|
||||||
|
removeFileAndParents(www, pluginRelativePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports.getInstaller = function (type) {
|
||||||
|
if (handlers[type] && handlers[type].install) {
|
||||||
|
return handlers[type].install;
|
||||||
|
}
|
||||||
|
|
||||||
|
events.emit('verbose', '<' + type + '> is not supported for android plugins');
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports.getUninstaller = function(type) {
|
||||||
|
if (handlers[type] && handlers[type].uninstall) {
|
||||||
|
return handlers[type].uninstall;
|
||||||
|
}
|
||||||
|
|
||||||
|
events.emit('verbose', '<' + type + '> is not supported for android plugins');
|
||||||
|
};
|
||||||
|
|
||||||
|
function copyFile (plugin_dir, src, project_dir, dest, link) {
|
||||||
|
src = path.resolve(plugin_dir, src);
|
||||||
|
if (!fs.existsSync(src)) throw new CordovaError('"' + src + '" not found!');
|
||||||
|
|
||||||
|
// check that src path is inside plugin directory
|
||||||
|
var real_path = fs.realpathSync(src);
|
||||||
|
var real_plugin_path = fs.realpathSync(plugin_dir);
|
||||||
|
if (real_path.indexOf(real_plugin_path) !== 0)
|
||||||
|
throw new CordovaError('"' + src + '" not located within plugin!');
|
||||||
|
|
||||||
|
dest = path.resolve(project_dir, dest);
|
||||||
|
|
||||||
|
// check that dest path is located in project directory
|
||||||
|
if (dest.indexOf(project_dir) !== 0)
|
||||||
|
throw new CordovaError('"' + dest + '" not located within project!');
|
||||||
|
|
||||||
|
shell.mkdir('-p', path.dirname(dest));
|
||||||
|
|
||||||
|
if (link) {
|
||||||
|
fs.symlinkSync(path.relative(path.dirname(dest), src), dest);
|
||||||
|
} else if (fs.statSync(src).isDirectory()) {
|
||||||
|
// XXX shelljs decides to create a directory when -R|-r is used which sucks. http://goo.gl/nbsjq
|
||||||
|
shell.cp('-Rf', src+'/*', dest);
|
||||||
|
} else {
|
||||||
|
shell.cp('-f', src, dest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Same as copy file but throws error if target exists
|
||||||
|
function copyNewFile (plugin_dir, src, project_dir, dest, link) {
|
||||||
|
var target_path = path.resolve(project_dir, dest);
|
||||||
|
if (fs.existsSync(target_path))
|
||||||
|
throw new CordovaError('"' + target_path + '" already exists!');
|
||||||
|
|
||||||
|
copyFile(plugin_dir, src, project_dir, dest, !!link);
|
||||||
|
}
|
||||||
|
|
||||||
|
// checks if file exists and then deletes. Error if doesn't exist
|
||||||
|
function removeFile (project_dir, src) {
|
||||||
|
var file = path.resolve(project_dir, src);
|
||||||
|
shell.rm('-Rf', file);
|
||||||
|
}
|
||||||
|
|
||||||
|
// deletes file/directory without checking
|
||||||
|
function removeFileF (file) {
|
||||||
|
shell.rm('-Rf', file);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sometimes we want to remove some java, and prune any unnecessary empty directories
|
||||||
|
function deleteJava (project_dir, destFile) {
|
||||||
|
removeFileAndParents(project_dir, destFile, 'src');
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeFileAndParents (baseDir, destFile, stopper) {
|
||||||
|
stopper = stopper || '.';
|
||||||
|
var file = path.resolve(baseDir, destFile);
|
||||||
|
if (!fs.existsSync(file)) return;
|
||||||
|
|
||||||
|
removeFileF(file);
|
||||||
|
|
||||||
|
// check if directory is empty
|
||||||
|
var curDir = path.dirname(file);
|
||||||
|
|
||||||
|
while(curDir !== path.resolve(baseDir, stopper)) {
|
||||||
|
if(fs.existsSync(curDir) && fs.readdirSync(curDir).length === 0) {
|
||||||
|
fs.rmdirSync(curDir);
|
||||||
|
curDir = path.resolve(curDir, '..');
|
||||||
|
} else {
|
||||||
|
// directory not empty...do nothing
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
364
bin/templates/cordova/lib/prepare.js
vendored
Normal file
364
bin/templates/cordova/lib/prepare.js
vendored
Normal file
@ -0,0 +1,364 @@
|
|||||||
|
/**
|
||||||
|
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 Q = require('q');
|
||||||
|
var fs = require('fs');
|
||||||
|
var path = require('path');
|
||||||
|
var shell = require('shelljs');
|
||||||
|
var events = require('cordova-common').events;
|
||||||
|
var AndroidManifest = require('./AndroidManifest');
|
||||||
|
var xmlHelpers = require('cordova-common').xmlHelpers;
|
||||||
|
var CordovaError = require('cordova-common').CordovaError;
|
||||||
|
var ConfigParser = require('cordova-common').ConfigParser;
|
||||||
|
|
||||||
|
module.exports.prepare = function (cordovaProject) {
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
this._config = updateConfigFilesFrom(cordovaProject.projectConfig,
|
||||||
|
this._munger, this.locations);
|
||||||
|
|
||||||
|
// Update own www dir with project's www assets and plugins' assets and js-files
|
||||||
|
return Q.when(updateWwwFrom(cordovaProject, this.locations))
|
||||||
|
.then(function () {
|
||||||
|
// update project according to config.xml changes.
|
||||||
|
return updateProjectAccordingTo(self._config, self.locations);
|
||||||
|
})
|
||||||
|
.then(function () {
|
||||||
|
handleIcons(cordovaProject.projectConfig, self.root);
|
||||||
|
handleSplashes(cordovaProject.projectConfig, self.root);
|
||||||
|
})
|
||||||
|
.then(function () {
|
||||||
|
self.events.emit('verbose', 'updated project successfully');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates config files in project based on app's config.xml and config munge,
|
||||||
|
* generated by plugins.
|
||||||
|
*
|
||||||
|
* @param {ConfigParser} sourceConfig A project's configuration that will
|
||||||
|
* be merged into platform's config.xml
|
||||||
|
* @param {ConfigChanges} configMunger An initialized ConfigChanges instance
|
||||||
|
* for this platform.
|
||||||
|
* @param {Object} locations A map of locations for this platform
|
||||||
|
*
|
||||||
|
* @return {ConfigParser} An instance of ConfigParser, that
|
||||||
|
* represents current project's configuration. When returned, the
|
||||||
|
* configuration is already dumped to appropriate config.xml file.
|
||||||
|
*/
|
||||||
|
function updateConfigFilesFrom(sourceConfig, configMunger, locations) {
|
||||||
|
events.emit('verbose', 'Generating config.xml from defaults for platform "android"');
|
||||||
|
|
||||||
|
// First cleanup current config and merge project's one into own
|
||||||
|
// Overwrite platform config.xml with defaults.xml.
|
||||||
|
shell.cp('-f', locations.defaultConfigXml, locations.configXml);
|
||||||
|
|
||||||
|
// Then apply config changes from global munge to all config files
|
||||||
|
// in project (including project's config)
|
||||||
|
configMunger.reapply_global_munge().save_all();
|
||||||
|
|
||||||
|
// Merge changes from app's config.xml into platform's one
|
||||||
|
var config = new ConfigParser(locations.configXml);
|
||||||
|
xmlHelpers.mergeXml(sourceConfig.doc.getroot(),
|
||||||
|
config.doc.getroot(), 'android', /*clobber=*/true);
|
||||||
|
|
||||||
|
config.write();
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates platform 'www' directory by replacing it with contents of
|
||||||
|
* 'platform_www' and app www. Also copies project's overrides' folder into
|
||||||
|
* the platform 'www' folder
|
||||||
|
*
|
||||||
|
* @param {Object} cordovaProject An object which describes cordova project.
|
||||||
|
* @param {Object} destinations An object that contains destination
|
||||||
|
* paths for www files.
|
||||||
|
*/
|
||||||
|
function updateWwwFrom(cordovaProject, destinations) {
|
||||||
|
shell.rm('-rf', destinations.www);
|
||||||
|
shell.mkdir('-p', destinations.www);
|
||||||
|
// Copy source files from project's www directory
|
||||||
|
shell.cp('-rf', path.join(cordovaProject.locations.www, '*'), destinations.www);
|
||||||
|
// Override www sources by files in 'platform_www' directory
|
||||||
|
shell.cp('-rf', path.join(destinations.platformWww, '*'), destinations.www);
|
||||||
|
|
||||||
|
// If project contains 'merges' for our platform, use them as another overrides
|
||||||
|
var merges_path = path.join(cordovaProject.root, 'merges', 'android');
|
||||||
|
if (fs.existsSync(merges_path)) {
|
||||||
|
events.emit('verbose', 'Found "merges" for android platform. Copying over existing "www" files.');
|
||||||
|
var overrides = path.join(merges_path, '*');
|
||||||
|
shell.cp('-rf', overrides, destinations.www);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates project structure and AndroidManifest according to project's configuration.
|
||||||
|
*
|
||||||
|
* @param {ConfigParser} platformConfig A project's configuration that will
|
||||||
|
* be used to update project
|
||||||
|
* @param {Object} locations A map of locations for this platform
|
||||||
|
*/
|
||||||
|
function updateProjectAccordingTo(platformConfig, locations) {
|
||||||
|
// Update app name by editing res/values/strings.xml
|
||||||
|
var name = platformConfig.name();
|
||||||
|
var strings = xmlHelpers.parseElementtreeSync(locations.strings);
|
||||||
|
strings.find('string[@name="app_name"]').text = name;
|
||||||
|
fs.writeFileSync(locations.strings, strings.write({indent: 4}), 'utf-8');
|
||||||
|
events.emit('verbose', 'Wrote out Android application name to "' + name + '"');
|
||||||
|
|
||||||
|
// Java packages cannot support dashes
|
||||||
|
var pkg = (platformConfig.android_packageName() || platformConfig.packageName()).replace(/-/g, '_');
|
||||||
|
|
||||||
|
var manifest = new AndroidManifest(locations.manifest);
|
||||||
|
var orig_pkg = manifest.getPackageId();
|
||||||
|
|
||||||
|
manifest.getActivity()
|
||||||
|
.setOrientation(findOrientationValue(platformConfig))
|
||||||
|
.setLaunchMode(findAndroidLaunchModePreference(platformConfig));
|
||||||
|
|
||||||
|
manifest.setVersionName(platformConfig.version())
|
||||||
|
.setVersionCode(platformConfig.android_versionCode() || default_versionCode(platformConfig.version()))
|
||||||
|
.setPackageId(pkg)
|
||||||
|
.setMinSdkVersion(platformConfig.getPreference('android-minSdkVersion', 'android'))
|
||||||
|
.setMaxSdkVersion(platformConfig.getPreference('android-maxSdkVersion', 'android'))
|
||||||
|
.setTargetSdkVersion(platformConfig.getPreference('android-targetSdkVersion', 'android'))
|
||||||
|
.write();
|
||||||
|
|
||||||
|
var javaPattern = path.join(locations.root, 'src', orig_pkg.replace(/\./g, '/'), '*.java');
|
||||||
|
var java_files = shell.ls(javaPattern).filter(function(f) {
|
||||||
|
return shell.grep(/extends\s+CordovaActivity/g, f);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (java_files.length === 0) {
|
||||||
|
throw new CordovaError('No Java files found which extend CordovaActivity.');
|
||||||
|
} else if(java_files.length > 1) {
|
||||||
|
events.emit('log', 'Multiple candidate Java files (.java files which extend CordovaActivity) found. Guessing at the first one, ' + java_files[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
var destFile = path.join(locations.root, 'src', pkg.replace(/\./g, '/'), path.basename(java_files[0]));
|
||||||
|
shell.mkdir('-p', path.dirname(destFile));
|
||||||
|
shell.sed(/package [\w\.]*;/, 'package ' + pkg + ';', java_files[0]).to(destFile);
|
||||||
|
events.emit('verbose', 'Wrote out Android package name to "' + pkg + '"');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Consturct the default value for versionCode as
|
||||||
|
// PATCH + MINOR * 100 + MAJOR * 10000
|
||||||
|
// see http://developer.android.com/tools/publishing/versioning.html
|
||||||
|
function default_versionCode(version) {
|
||||||
|
var nums = version.split('-')[0].split('.');
|
||||||
|
var versionCode = 0;
|
||||||
|
if (+nums[0]) {
|
||||||
|
versionCode += +nums[0] * 10000;
|
||||||
|
}
|
||||||
|
if (+nums[1]) {
|
||||||
|
versionCode += +nums[1] * 100;
|
||||||
|
}
|
||||||
|
if (+nums[2]) {
|
||||||
|
versionCode += +nums[2];
|
||||||
|
}
|
||||||
|
return versionCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
function copyImage(src, resourcesDir, density, name) {
|
||||||
|
var destFolder = path.join(resourcesDir, (density ? 'drawable-': 'drawable') + density);
|
||||||
|
var isNinePatch = !!/\.9\.png$/.exec(src);
|
||||||
|
var ninePatchName = name.replace(/\.png$/, '.9.png');
|
||||||
|
|
||||||
|
// default template does not have default asset for this density
|
||||||
|
if (!fs.existsSync(destFolder)) {
|
||||||
|
fs.mkdirSync(destFolder);
|
||||||
|
}
|
||||||
|
|
||||||
|
var destFilePath = path.join(destFolder, isNinePatch ? ninePatchName : name);
|
||||||
|
events.emit('verbose', 'copying image from ' + src + ' to ' + destFilePath);
|
||||||
|
shell.cp('-f', src, destFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleSplashes(projectConfig, platformRoot) {
|
||||||
|
var resources = projectConfig.getSplashScreens('android');
|
||||||
|
// if there are "splash" elements in config.xml
|
||||||
|
if (resources.length > 0) {
|
||||||
|
deleteDefaultResourceAt(platformRoot, 'screen.png');
|
||||||
|
events.emit('verbose', 'splash screens: ' + JSON.stringify(resources));
|
||||||
|
|
||||||
|
// The source paths for icons and splashes are relative to
|
||||||
|
// project's config.xml location, so we use it as base path.
|
||||||
|
var projectRoot = path.dirname(projectConfig.path);
|
||||||
|
var destination = path.join(platformRoot, 'res');
|
||||||
|
|
||||||
|
var hadMdpi = false;
|
||||||
|
resources.forEach(function (resource) {
|
||||||
|
if (!resource.density) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (resource.density == 'mdpi') {
|
||||||
|
hadMdpi = true;
|
||||||
|
}
|
||||||
|
copyImage(path.join(projectRoot, resource.src), destination, resource.density, 'screen.png');
|
||||||
|
});
|
||||||
|
// There's no "default" drawable, so assume default == mdpi.
|
||||||
|
if (!hadMdpi && resources.defaultResource) {
|
||||||
|
copyImage(path.join(projectRoot, resources.defaultResource.src), destination, 'mdpi', 'screen.png');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleIcons(projectConfig, platformRoot) {
|
||||||
|
var icons = projectConfig.getIcons('android');
|
||||||
|
|
||||||
|
// if there are icon elements in config.xml
|
||||||
|
if (icons.length === 0) {
|
||||||
|
events.emit('verbose', 'This app does not have launcher icons defined');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteDefaultResourceAt(platformRoot, 'icon.png');
|
||||||
|
|
||||||
|
var android_icons = {};
|
||||||
|
var default_icon;
|
||||||
|
// http://developer.android.com/design/style/iconography.html
|
||||||
|
var sizeToDensityMap = {
|
||||||
|
36: 'ldpi',
|
||||||
|
48: 'mdpi',
|
||||||
|
72: 'hdpi',
|
||||||
|
96: 'xhdpi',
|
||||||
|
144: 'xxhdpi',
|
||||||
|
192: 'xxxhdpi'
|
||||||
|
};
|
||||||
|
// find the best matching icon for a given density or size
|
||||||
|
// @output android_icons
|
||||||
|
var parseIcon = function(icon, icon_size) {
|
||||||
|
// do I have a platform icon for that density already
|
||||||
|
var density = icon.density || sizeToDensityMap[icon_size];
|
||||||
|
if (!density) {
|
||||||
|
// invalid icon defition ( or unsupported size)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var previous = android_icons[density];
|
||||||
|
if (previous && previous.platform) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
android_icons[density] = icon;
|
||||||
|
};
|
||||||
|
|
||||||
|
// iterate over all icon elements to find the default icon and call parseIcon
|
||||||
|
for (var i=0; i<icons.length; i++) {
|
||||||
|
var icon = icons[i];
|
||||||
|
var size = icon.width;
|
||||||
|
if (!size) {
|
||||||
|
size = icon.height;
|
||||||
|
}
|
||||||
|
if (!size && !icon.density) {
|
||||||
|
if (default_icon) {
|
||||||
|
events.emit('verbose', 'more than one default icon: ' + JSON.stringify(icon));
|
||||||
|
} else {
|
||||||
|
default_icon = icon;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
parseIcon(icon, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The source paths for icons and splashes are relative to
|
||||||
|
// project's config.xml location, so we use it as base path.
|
||||||
|
var projectRoot = path.dirname(projectConfig.path);
|
||||||
|
var destination = path.join(platformRoot, 'res');
|
||||||
|
for (var density in android_icons) {
|
||||||
|
copyImage(path.join(projectRoot, android_icons[density].src), destination, density, 'icon.png');
|
||||||
|
}
|
||||||
|
// There's no "default" drawable, so assume default == mdpi.
|
||||||
|
if (default_icon && !android_icons.mdpi) {
|
||||||
|
copyImage(path.join(projectRoot, default_icon.src), destination, 'mdpi', 'icon.png');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove the default resource name from all drawable folders
|
||||||
|
function deleteDefaultResourceAt(baseDir, resourceName) {
|
||||||
|
shell.ls(path.join(baseDir, 'res/drawable-*'))
|
||||||
|
.forEach(function (drawableFolder) {
|
||||||
|
var imagePath = path.join(drawableFolder, resourceName);
|
||||||
|
shell.rm('-f', [imagePath, imagePath.replace(/\.png$/, '.9.png')]);
|
||||||
|
events.emit('verbose', 'Deleted ' + imagePath);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets and validates 'AndroidLaunchMode' prepference from config.xml. Returns
|
||||||
|
* preference value and warns if it doesn't seems to be valid
|
||||||
|
*
|
||||||
|
* @param {ConfigParser} platformConfig A configParser instance for
|
||||||
|
* platform.
|
||||||
|
*
|
||||||
|
* @return {String} Preference's value from config.xml or
|
||||||
|
* default value, if there is no such preference. The default value is
|
||||||
|
* 'singleTop'
|
||||||
|
*/
|
||||||
|
function findAndroidLaunchModePreference(platformConfig) {
|
||||||
|
var launchMode = platformConfig.getPreference('AndroidLaunchMode');
|
||||||
|
if (!launchMode) {
|
||||||
|
// Return a default value
|
||||||
|
return 'singleTop';
|
||||||
|
}
|
||||||
|
|
||||||
|
var expectedValues = ['standard', 'singleTop', 'singleTask', 'singleInstance'];
|
||||||
|
var valid = expectedValues.indexOf(launchMode) >= 0;
|
||||||
|
if (!valid) {
|
||||||
|
// Note: warn, but leave the launch mode as developer wanted, in case the list of options changes in the future
|
||||||
|
events.emit('warn', 'Unrecognized value for AndroidLaunchMode preference: ' +
|
||||||
|
launchMode + '. Expected values are: ' + expectedValues.join(', '));
|
||||||
|
}
|
||||||
|
|
||||||
|
return launchMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Queries ConfigParser object for the orientation <preference> value. Warns if
|
||||||
|
* global preference value is not supported by platform.
|
||||||
|
*
|
||||||
|
* @param {Object} platformConfig ConfigParser object
|
||||||
|
*
|
||||||
|
* @return {String} Global/platform-specific orientation in lower-case
|
||||||
|
* (or empty string if both are undefined).
|
||||||
|
*/
|
||||||
|
function findOrientationValue(platformConfig) {
|
||||||
|
|
||||||
|
var ORIENTATION_DEFAULT = 'default';
|
||||||
|
|
||||||
|
var orientation = platformConfig.getPreference('orientation');
|
||||||
|
if (!orientation) {
|
||||||
|
return ORIENTATION_DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
var GLOBAL_ORIENTATIONS = ['default', 'portrait','landscape'];
|
||||||
|
function isSupported(orientation) {
|
||||||
|
return GLOBAL_ORIENTATIONS.indexOf(orientation.toLowerCase()) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the given global orientation is supported
|
||||||
|
if (orientation && isSupported(orientation)) {
|
||||||
|
return orientation;
|
||||||
|
}
|
||||||
|
|
||||||
|
events.emit('warn', 'Unsupported global orientation: ' + orientation +
|
||||||
|
'. Defaulting to value: ' + ORIENTATION_DEFAULT);
|
||||||
|
return ORIENTATION_DEFAULT;
|
||||||
|
}
|
6
bin/templates/cordova/lib/retry.js
vendored
6
bin/templates/cordova/lib/retry.js
vendored
@ -21,7 +21,9 @@
|
|||||||
|
|
||||||
/* jshint node: true */
|
/* jshint node: true */
|
||||||
|
|
||||||
"use strict";
|
'use strict';
|
||||||
|
|
||||||
|
var events = require('cordova-common').events;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Retry a promise-returning function a number of times, propagating its
|
* Retry a promise-returning function a number of times, propagating its
|
||||||
@ -56,7 +58,7 @@ module.exports.retryPromise = function (attemts_left, promiseFunction) {
|
|||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("A retried call failed. Retrying " + attemts_left + " more time(s).");
|
events.emit('verbose', 'A retried call failed. Retrying ' + attemts_left + ' more time(s).');
|
||||||
|
|
||||||
// retry call self again with the same arguments, except attemts_left is now lower
|
// retry call self again with the same arguments, except attemts_left is now lower
|
||||||
var fullArguments = [attemts_left, promiseFunction].concat(promiseFunctionArguments);
|
var fullArguments = [attemts_left, promiseFunction].concat(promiseFunctionArguments);
|
||||||
|
80
bin/templates/cordova/lib/run.js
vendored
80
bin/templates/cordova/lib/run.js
vendored
@ -25,63 +25,25 @@ var path = require('path'),
|
|||||||
build = require('./build'),
|
build = require('./build'),
|
||||||
emulator = require('./emulator'),
|
emulator = require('./emulator'),
|
||||||
device = require('./device'),
|
device = require('./device'),
|
||||||
shell = require('shelljs'),
|
|
||||||
Q = require('q');
|
Q = require('q');
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Runs the application on a device if available.
|
* Runs the application on a device if available. If no device is found, it will
|
||||||
* If no device is found, it will use a started emulator.
|
* use a started emulator. If no started emulators are found it will attempt
|
||||||
* If no started emulators are found it will attempt to start an avd.
|
* to start an avd. If no avds are found it will error out.
|
||||||
* If no avds are found it will error out.
|
*
|
||||||
* Returns a promise.
|
* @param {Object} runOptions various run/build options. See Api.js build/run
|
||||||
|
* methods for reference.
|
||||||
|
*
|
||||||
|
* @return {Promise}
|
||||||
*/
|
*/
|
||||||
module.exports.run = function(args) {
|
module.exports.run = function(runOptions) {
|
||||||
var buildFlags = [];
|
|
||||||
var install_target;
|
|
||||||
var list = false;
|
|
||||||
|
|
||||||
for (var i=2; i<args.length; i++) {
|
var self = this;
|
||||||
if (build.isBuildFlag(args[i])) {
|
|
||||||
buildFlags.push(args[i]);
|
|
||||||
} else if (args[i] == '--device') {
|
|
||||||
install_target = '--device';
|
|
||||||
} else if (args[i] == '--emulator') {
|
|
||||||
install_target = '--emulator';
|
|
||||||
} else if (/^--target=/.exec(args[i])) {
|
|
||||||
install_target = args[i].substring(9, args[i].length);
|
|
||||||
} else if (args[i] == '--list') {
|
|
||||||
list = true;
|
|
||||||
} else {
|
|
||||||
console.warn('Option \'' + args[i] + '\' not recognized (ignoring).');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (list) {
|
var install_target = runOptions.device ? '--device' :
|
||||||
var output = '';
|
runOptions.emulator ? '--emulator' :
|
||||||
var temp = '';
|
runOptions.target;
|
||||||
if (!install_target) {
|
|
||||||
output += 'Available Android Devices:\n';
|
|
||||||
temp = shell.exec(path.join(__dirname, 'list-devices'), {silent:true}).output;
|
|
||||||
temp = temp.replace(/^(?=[^\s])/gm, '\t');
|
|
||||||
output += temp;
|
|
||||||
output += 'Available Android Virtual Devices:\n';
|
|
||||||
temp = shell.exec(path.join(__dirname, 'list-emulator-images'), {silent:true}).output;
|
|
||||||
temp = temp.replace(/^(?=[^\s])/gm, '\t');
|
|
||||||
output += temp;
|
|
||||||
} else if (install_target == '--emulator') {
|
|
||||||
output += 'Available Android Virtual Devices:\n';
|
|
||||||
temp = shell.exec(path.join(__dirname, 'list-emulator-images'), {silent:true}).output;
|
|
||||||
temp = temp.replace(/^(?=[^\s])/gm, '\t');
|
|
||||||
output += temp;
|
|
||||||
} else if (install_target == '--device') {
|
|
||||||
output += 'Available Android Devices:\n';
|
|
||||||
temp = shell.exec(path.join(__dirname, 'list-devices'), {silent:true}).output;
|
|
||||||
temp = temp.replace(/^(?=[^\s])/gm, '\t');
|
|
||||||
output += temp;
|
|
||||||
}
|
|
||||||
console.log(output);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Q()
|
return Q()
|
||||||
.then(function() {
|
.then(function() {
|
||||||
@ -90,10 +52,10 @@ var path = require('path'),
|
|||||||
return device.list()
|
return device.list()
|
||||||
.then(function(device_list) {
|
.then(function(device_list) {
|
||||||
if (device_list.length > 0) {
|
if (device_list.length > 0) {
|
||||||
console.log('WARNING : No target specified, deploying to device \'' + device_list[0] + '\'.');
|
self.events.emit('warn', 'No target specified, deploying to device \'' + device_list[0] + '\'.');
|
||||||
install_target = device_list[0];
|
install_target = device_list[0];
|
||||||
} else {
|
} else {
|
||||||
console.log('WARNING : No target specified, deploying to emulator');
|
self.events.emit('warn', 'No target specified, deploying to emulator');
|
||||||
install_target = '--emulator';
|
install_target = '--emulator';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -137,9 +99,15 @@ var path = require('path'),
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}).then(function(resolvedTarget) {
|
}).then(function(resolvedTarget) {
|
||||||
return build.run(buildFlags, resolvedTarget).then(function(buildResults) {
|
// Better just call self.build, but we're doing some processing of
|
||||||
|
// build results (according to platformApi spec) so they are in different
|
||||||
|
// format than emulator.install expects.
|
||||||
|
// TODO: Update emulator/device.install to handle this change
|
||||||
|
return build.run.call(self, runOptions, resolvedTarget)
|
||||||
|
.then(function(buildResults) {
|
||||||
if (resolvedTarget.isEmulator) {
|
if (resolvedTarget.isEmulator) {
|
||||||
return emulator.wait_for_boot(resolvedTarget.target).then(function () {
|
return emulator.wait_for_boot(resolvedTarget.target)
|
||||||
|
.then(function () {
|
||||||
return emulator.install(resolvedTarget, buildResults);
|
return emulator.install(resolvedTarget, buildResults);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
50
bin/templates/cordova/lib/spawn.js
vendored
50
bin/templates/cordova/lib/spawn.js
vendored
@ -1,50 +0,0 @@
|
|||||||
#!/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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var child_process = require('child_process'),
|
|
||||||
Q = require('q');
|
|
||||||
var isWindows = process.platform.slice(0, 3) == 'win';
|
|
||||||
|
|
||||||
// Takes a command and optional current working directory.
|
|
||||||
module.exports = function(cmd, args, opt_cwd) {
|
|
||||||
var d = Q.defer();
|
|
||||||
var opts = { cwd: opt_cwd, stdio: 'inherit' };
|
|
||||||
try {
|
|
||||||
// Work around spawn not being able to find .bat files.
|
|
||||||
if (isWindows) {
|
|
||||||
args = [['/s', '/c', '"' + [cmd].concat(args).map(function(a){if (/^[^"].* .*[^"]/.test(a)) return '"' + a + '"'; return a;}).join(' ')+'"'].join(' ')];
|
|
||||||
cmd = 'cmd';
|
|
||||||
opts.windowsVerbatimArguments = true;
|
|
||||||
}
|
|
||||||
var child = child_process.spawn(cmd, args, opts);
|
|
||||||
child.on('exit', function(code) {
|
|
||||||
if (code) {
|
|
||||||
d.reject('Error code ' + code + ' for command: ' + cmd + ' with args: ' + args);
|
|
||||||
} else {
|
|
||||||
d.resolve();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch(e) {
|
|
||||||
console.error('error caught: ' + e);
|
|
||||||
d.reject(e);
|
|
||||||
}
|
|
||||||
return d.promise;
|
|
||||||
};
|
|
@ -19,19 +19,33 @@
|
|||||||
under the License.
|
under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var run = require('./lib/run'),
|
var Api = require('./Api');
|
||||||
reqs = require('./lib/check_reqs'),
|
var nopt = require('nopt');
|
||||||
args = process.argv;
|
var path = require('path');
|
||||||
|
|
||||||
// Support basic help commands
|
// Support basic help commands
|
||||||
if (args[2] == '--help' || args[2] == '/?' || args[2] == '-h' ||
|
if(['--help', '/?', '-h', 'help', '-help', '/help'].indexOf(process.argv[2]) >= 0)
|
||||||
args[2] == 'help' || args[2] == '-help' || args[2] == '/help') {
|
require('./lib/run').help();
|
||||||
run.help(args);
|
|
||||||
} else {
|
// Do some basic argument parsing
|
||||||
reqs.run().done(function() {
|
var runOpts = nopt({
|
||||||
return run.run(args);
|
'verbose' : Boolean,
|
||||||
}, function(err) {
|
'silent' : Boolean,
|
||||||
console.error('ERROR: ' + err);
|
'debug' : Boolean,
|
||||||
process.exit(2);
|
'release' : Boolean,
|
||||||
});
|
'nobuild': Boolean,
|
||||||
}
|
'buildConfig' : path,
|
||||||
|
'archs' : String,
|
||||||
|
'device' : Boolean,
|
||||||
|
'emulator': Boolean,
|
||||||
|
'target' : String
|
||||||
|
}, { 'd' : '--verbose' });
|
||||||
|
|
||||||
|
// Make runOptions compatible with PlatformApi run method spec
|
||||||
|
runOpts.argv = runOpts.argv.remain;
|
||||||
|
|
||||||
|
new Api().run(runOpts)
|
||||||
|
.catch(function(err) {
|
||||||
|
console.error(err, err.stack);
|
||||||
|
process.exit(2);
|
||||||
|
});
|
||||||
|
@ -22,4 +22,8 @@
|
|||||||
// Coho updates this line:
|
// Coho updates this line:
|
||||||
var VERSION = "5.0.0-dev";
|
var VERSION = "5.0.0-dev";
|
||||||
|
|
||||||
console.log(VERSION);
|
module.exports.version = VERSION;
|
||||||
|
|
||||||
|
if (!module.parent) {
|
||||||
|
console.log(VERSION);
|
||||||
|
}
|
||||||
|
66
bin/update
66
bin/update
@ -1,31 +1,35 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Licensed to the Apache Software Foundation (ASF) under one
|
Licensed to the Apache Software Foundation (ASF) under one
|
||||||
or more contributor license agreements. See the NOTICE file
|
or more contributor license agreements. See the NOTICE file
|
||||||
distributed with this work for additional information
|
distributed with this work for additional information
|
||||||
regarding copyright ownership. The ASF licenses this file
|
regarding copyright ownership. The ASF licenses this file
|
||||||
to you under the Apache License, Version 2.0 (the
|
to you under the Apache License, Version 2.0 (the
|
||||||
"License"); you may not use this file except in compliance
|
"License"); you may not use this file except in compliance
|
||||||
with the License. You may obtain a copy of the License at
|
with the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing,
|
Unless required by applicable law or agreed to in writing,
|
||||||
software distributed under the License is distributed on an
|
software distributed under the License is distributed on an
|
||||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
KIND, either express or implied. See the License for the
|
KIND, either express or implied. See the License for the
|
||||||
specific language governing permissions and limitations
|
specific language governing permissions and limitations
|
||||||
under the License.
|
under the License.
|
||||||
*/
|
*/
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
var create = require('./lib/create');
|
var Api = require('./templates/cordova/Api');
|
||||||
var args = require('./lib/simpleargs').getArgs(process.argv);
|
var args = require('nopt')({
|
||||||
|
'link': Boolean,
|
||||||
if (args['--help'] || args._.length === 0) {
|
'shared': Boolean,
|
||||||
console.log('Usage: ' + path.relative(process.cwd(), path.join(__dirname, 'update')) + ' <path_to_project> [--link]');
|
'help': Boolean
|
||||||
console.log(' --link will use the CordovaLib project directly instead of making a copy.');
|
});
|
||||||
process.exit(1);
|
|
||||||
}
|
if (args.help || args.argv.remain.length === 0) {
|
||||||
create.updateProject(args._[0], args['--link'] || args['--shared']).done();
|
console.log('Usage: ' + path.relative(process.cwd(), path.join(__dirname, 'update')) + ' <path_to_project> [--link]');
|
||||||
|
console.log(' --link will use the CordovaLib project directly instead of making a copy.');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Api.updatePlatform(args.argv.remain[0], {link: (args.link || args.shared)}).done();
|
||||||
|
1
node_modules/elementtree/.npmignore
generated
vendored
Normal file
1
node_modules/elementtree/.npmignore
generated
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
node_modules
|
10
node_modules/elementtree/.travis.yml
generated
vendored
Normal file
10
node_modules/elementtree/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
language: node_js
|
||||||
|
|
||||||
|
node_js:
|
||||||
|
- 0.6
|
||||||
|
|
||||||
|
script: make test
|
||||||
|
|
||||||
|
notifications:
|
||||||
|
email:
|
||||||
|
- tomaz+travisci@tomaz.me
|
39
node_modules/elementtree/CHANGES.md
generated
vendored
Normal file
39
node_modules/elementtree/CHANGES.md
generated
vendored
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
elementtree v0.1.6 (in development)
|
||||||
|
|
||||||
|
* Add support for CData elements. (#14)
|
||||||
|
[hermannpencole]
|
||||||
|
|
||||||
|
elementtree v0.1.5 - 2012-11-14
|
||||||
|
|
||||||
|
* Fix a bug in the find() and findtext() method which could manifest itself
|
||||||
|
under some conditions.
|
||||||
|
[metagriffin]
|
||||||
|
|
||||||
|
elementtree v0.1.4 - 2012-10-15
|
||||||
|
|
||||||
|
* Allow user to use namespaced attributes when using find* functions.
|
||||||
|
[Andrew Lunny]
|
||||||
|
|
||||||
|
elementtree v0.1.3 - 2012-09-21
|
||||||
|
|
||||||
|
* Improve the output of text content in the tags (strip unnecessary line break
|
||||||
|
characters).
|
||||||
|
|
||||||
|
[Darryl Pogue]
|
||||||
|
|
||||||
|
elementtree v0.1.2 - 2012-09-04
|
||||||
|
|
||||||
|
* Allow user to pass 'indent' option to ElementTree.write method. If this
|
||||||
|
option is specified (e.g. {'indent': 4}). XML will be pretty printed.
|
||||||
|
[Darryl Pogue, Tomaz Muraus]
|
||||||
|
|
||||||
|
* Bump sax dependency version.
|
||||||
|
|
||||||
|
elementtree v0.1.1 - 2011-09-23
|
||||||
|
|
||||||
|
* Improve special character escaping.
|
||||||
|
[Ryan Phillips]
|
||||||
|
|
||||||
|
elementtree v0.1.0 - 2011-09-05
|
||||||
|
|
||||||
|
* Initial release.
|
203
node_modules/elementtree/LICENSE.txt
generated
vendored
Normal file
203
node_modules/elementtree/LICENSE.txt
generated
vendored
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
|
||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
21
node_modules/elementtree/Makefile
generated
vendored
Normal file
21
node_modules/elementtree/Makefile
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
TESTS := \
|
||||||
|
tests/test-simple.js
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
PATH := ./node_modules/.bin:$(PATH)
|
||||||
|
|
||||||
|
WHISKEY := $(shell bash -c 'PATH=$(PATH) type -p whiskey')
|
||||||
|
|
||||||
|
default: test
|
||||||
|
|
||||||
|
test:
|
||||||
|
NODE_PATH=`pwd`/lib/ ${WHISKEY} --scope-leaks --sequential --real-time --tests "${TESTS}"
|
||||||
|
|
||||||
|
tap:
|
||||||
|
NODE_PATH=`pwd`/lib/ ${WHISKEY} --test-reporter tap --sequential --real-time --tests "${TESTS}"
|
||||||
|
|
||||||
|
coverage:
|
||||||
|
NODE_PATH=`pwd`/lib/ ${WHISKEY} --sequential --coverage --coverage-reporter html --coverage-dir coverage_html --tests "${TESTS}"
|
||||||
|
|
||||||
|
.PHONY: default test coverage tap scope
|
5
node_modules/elementtree/NOTICE
generated
vendored
Normal file
5
node_modules/elementtree/NOTICE
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
node-elementtree
|
||||||
|
Copyright (c) 2011, Rackspace, Inc.
|
||||||
|
|
||||||
|
The ElementTree toolkit is Copyright (c) 1999-2007 by Fredrik Lundh
|
||||||
|
|
141
node_modules/elementtree/README.md
generated
vendored
Normal file
141
node_modules/elementtree/README.md
generated
vendored
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
node-elementtree
|
||||||
|
====================
|
||||||
|
|
||||||
|
node-elementtree is a [Node.js](http://nodejs.org) XML parser and serializer based upon the [Python ElementTree v1.3](http://effbot.org/zone/element-index.htm) module.
|
||||||
|
|
||||||
|
Installation
|
||||||
|
====================
|
||||||
|
|
||||||
|
$ npm install elementtree
|
||||||
|
|
||||||
|
Using the library
|
||||||
|
====================
|
||||||
|
|
||||||
|
For the usage refer to the Python ElementTree library documentation - [http://effbot.org/zone/element-index.htm#usage](http://effbot.org/zone/element-index.htm#usage).
|
||||||
|
|
||||||
|
Supported XPath expressions in `find`, `findall` and `findtext` methods are listed on [http://effbot.org/zone/element-xpath.htm](http://effbot.org/zone/element-xpath.htm).
|
||||||
|
|
||||||
|
Example 1 – Creating An XML Document
|
||||||
|
====================
|
||||||
|
|
||||||
|
This example shows how to build a valid XML document that can be published to
|
||||||
|
Atom Hopper. Atom Hopper is used internally as a bridge from products all the
|
||||||
|
way to collecting revenue, called “Usage.” MaaS and other products send similar
|
||||||
|
events to it every time user performs an action on a resource
|
||||||
|
(e.g. creates,updates or deletes). Below is an example of leveraging the API
|
||||||
|
to create a new XML document.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var et = require('elementtree');
|
||||||
|
var XML = et.XML;
|
||||||
|
var ElementTree = et.ElementTree;
|
||||||
|
var element = et.Element;
|
||||||
|
var subElement = et.SubElement;
|
||||||
|
|
||||||
|
var date, root, tenantId, serviceName, eventType, usageId, dataCenter, region,
|
||||||
|
checks, resourceId, category, startTime, resourceName, etree, xml;
|
||||||
|
|
||||||
|
date = new Date();
|
||||||
|
|
||||||
|
root = element('entry');
|
||||||
|
root.set('xmlns', 'http://www.w3.org/2005/Atom');
|
||||||
|
|
||||||
|
tenantId = subElement(root, 'TenantId');
|
||||||
|
tenantId.text = '12345';
|
||||||
|
|
||||||
|
serviceName = subElement(root, 'ServiceName');
|
||||||
|
serviceName.text = 'MaaS';
|
||||||
|
|
||||||
|
resourceId = subElement(root, 'ResourceID');
|
||||||
|
resourceId.text = 'enAAAA';
|
||||||
|
|
||||||
|
usageId = subElement(root, 'UsageID');
|
||||||
|
usageId.text = '550e8400-e29b-41d4-a716-446655440000';
|
||||||
|
|
||||||
|
eventType = subElement(root, 'EventType');
|
||||||
|
eventType.text = 'create';
|
||||||
|
|
||||||
|
category = subElement(root, 'category');
|
||||||
|
category.set('term', 'monitoring.entity.create');
|
||||||
|
|
||||||
|
dataCenter = subElement(root, 'DataCenter');
|
||||||
|
dataCenter.text = 'global';
|
||||||
|
|
||||||
|
region = subElement(root, 'Region');
|
||||||
|
region.text = 'global';
|
||||||
|
|
||||||
|
startTime = subElement(root, 'StartTime');
|
||||||
|
startTime.text = date;
|
||||||
|
|
||||||
|
resourceName = subElement(root, 'ResourceName');
|
||||||
|
resourceName.text = 'entity';
|
||||||
|
|
||||||
|
etree = new ElementTree(root);
|
||||||
|
xml = etree.write({'xml_declaration': false});
|
||||||
|
console.log(xml);
|
||||||
|
```
|
||||||
|
|
||||||
|
As you can see, both et.Element and et.SubElement are factory methods which
|
||||||
|
return a new instance of Element and SubElement class, respectively.
|
||||||
|
When you create a new element (tag) you can use set method to set an attribute.
|
||||||
|
To set the tag value, assign a value to the .text attribute.
|
||||||
|
|
||||||
|
This example would output a document that looks like this:
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<entry xmlns="http://www.w3.org/2005/Atom">
|
||||||
|
<TenantId>12345</TenantId>
|
||||||
|
<ServiceName>MaaS</ServiceName>
|
||||||
|
<ResourceID>enAAAA</ResourceID>
|
||||||
|
<UsageID>550e8400-e29b-41d4-a716-446655440000</UsageID>
|
||||||
|
<EventType>create</EventType>
|
||||||
|
<category term="monitoring.entity.create"/>
|
||||||
|
<DataCenter>global</DataCenter>
|
||||||
|
<Region>global</Region>
|
||||||
|
<StartTime>Sun Apr 29 2012 16:37:32 GMT-0700 (PDT)</StartTime>
|
||||||
|
<ResourceName>entity</ResourceName>
|
||||||
|
</entry>
|
||||||
|
```
|
||||||
|
|
||||||
|
Example 2 – Parsing An XML Document
|
||||||
|
====================
|
||||||
|
|
||||||
|
This example shows how to parse an XML document and use simple XPath selectors.
|
||||||
|
For demonstration purposes, we will use the XML document located at
|
||||||
|
https://gist.github.com/2554343.
|
||||||
|
|
||||||
|
Behind the scenes, node-elementtree uses Isaac’s sax library for parsing XML,
|
||||||
|
but the library has a concept of “parsers,” which means it’s pretty simple to
|
||||||
|
add support for a different parser.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var fs = require('fs');
|
||||||
|
|
||||||
|
var et = require('elementtree');
|
||||||
|
|
||||||
|
var XML = et.XML;
|
||||||
|
var ElementTree = et.ElementTree;
|
||||||
|
var element = et.Element;
|
||||||
|
var subElement = et.SubElement;
|
||||||
|
|
||||||
|
var data, etree;
|
||||||
|
|
||||||
|
data = fs.readFileSync('document.xml').toString();
|
||||||
|
etree = et.parse(data);
|
||||||
|
|
||||||
|
console.log(etree.findall('./entry/TenantId').length); // 2
|
||||||
|
console.log(etree.findtext('./entry/ServiceName')); // MaaS
|
||||||
|
console.log(etree.findall('./entry/category')[0].get('term')); // monitoring.entity.create
|
||||||
|
console.log(etree.findall('*/category/[@term="monitoring.entity.update"]').length); // 1
|
||||||
|
```
|
||||||
|
|
||||||
|
Build status
|
||||||
|
====================
|
||||||
|
|
||||||
|
[](http://travis-ci.org/racker/node-elementtree)
|
||||||
|
|
||||||
|
|
||||||
|
License
|
||||||
|
====================
|
||||||
|
|
||||||
|
node-elementtree is distributed under the [Apache license](http://www.apache.org/licenses/LICENSE-2.0.html).
|
20
node_modules/elementtree/lib/constants.js
generated
vendored
Normal file
20
node_modules/elementtree/lib/constants.js
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011 Rackspace
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
var DEFAULT_PARSER = 'sax';
|
||||||
|
|
||||||
|
exports.DEFAULT_PARSER = DEFAULT_PARSER;
|
343
node_modules/elementtree/lib/elementpath.js
generated
vendored
Normal file
343
node_modules/elementtree/lib/elementpath.js
generated
vendored
Normal file
@ -0,0 +1,343 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2011 Rackspace
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
var sprintf = require('./sprintf').sprintf;
|
||||||
|
|
||||||
|
var utils = require('./utils');
|
||||||
|
var SyntaxError = require('./errors').SyntaxError;
|
||||||
|
|
||||||
|
var _cache = {};
|
||||||
|
|
||||||
|
var RE = new RegExp(
|
||||||
|
"(" +
|
||||||
|
"'[^']*'|\"[^\"]*\"|" +
|
||||||
|
"::|" +
|
||||||
|
"//?|" +
|
||||||
|
"\\.\\.|" +
|
||||||
|
"\\(\\)|" +
|
||||||
|
"[/.*:\\[\\]\\(\\)@=])|" +
|
||||||
|
"((?:\\{[^}]+\\})?[^/\\[\\]\\(\\)@=\\s]+)|" +
|
||||||
|
"\\s+", 'g'
|
||||||
|
);
|
||||||
|
|
||||||
|
var xpath_tokenizer = utils.findall.bind(null, RE);
|
||||||
|
|
||||||
|
function prepare_tag(next, token) {
|
||||||
|
var tag = token[0];
|
||||||
|
|
||||||
|
function select(context, result) {
|
||||||
|
var i, len, elem, rv = [];
|
||||||
|
|
||||||
|
for (i = 0, len = result.length; i < len; i++) {
|
||||||
|
elem = result[i];
|
||||||
|
elem._children.forEach(function(e) {
|
||||||
|
if (e.tag === tag) {
|
||||||
|
rv.push(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
return select;
|
||||||
|
}
|
||||||
|
|
||||||
|
function prepare_star(next, token) {
|
||||||
|
function select(context, result) {
|
||||||
|
var i, len, elem, rv = [];
|
||||||
|
|
||||||
|
for (i = 0, len = result.length; i < len; i++) {
|
||||||
|
elem = result[i];
|
||||||
|
elem._children.forEach(function(e) {
|
||||||
|
rv.push(e);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
return select;
|
||||||
|
}
|
||||||
|
|
||||||
|
function prepare_dot(next, token) {
|
||||||
|
function select(context, result) {
|
||||||
|
var i, len, elem, rv = [];
|
||||||
|
|
||||||
|
for (i = 0, len = result.length; i < len; i++) {
|
||||||
|
elem = result[i];
|
||||||
|
rv.push(elem);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
return select;
|
||||||
|
}
|
||||||
|
|
||||||
|
function prepare_iter(next, token) {
|
||||||
|
var tag;
|
||||||
|
token = next();
|
||||||
|
|
||||||
|
if (token[1] === '*') {
|
||||||
|
tag = '*';
|
||||||
|
}
|
||||||
|
else if (!token[1]) {
|
||||||
|
tag = token[0] || '';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new SyntaxError(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
function select(context, result) {
|
||||||
|
var i, len, elem, rv = [];
|
||||||
|
|
||||||
|
for (i = 0, len = result.length; i < len; i++) {
|
||||||
|
elem = result[i];
|
||||||
|
elem.iter(tag, function(e) {
|
||||||
|
if (e !== elem) {
|
||||||
|
rv.push(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
return select;
|
||||||
|
}
|
||||||
|
|
||||||
|
function prepare_dot_dot(next, token) {
|
||||||
|
function select(context, result) {
|
||||||
|
var i, len, elem, rv = [], parent_map = context.parent_map;
|
||||||
|
|
||||||
|
if (!parent_map) {
|
||||||
|
context.parent_map = parent_map = {};
|
||||||
|
|
||||||
|
context.root.iter(null, function(p) {
|
||||||
|
p._children.forEach(function(e) {
|
||||||
|
parent_map[e] = p;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0, len = result.length; i < len; i++) {
|
||||||
|
elem = result[i];
|
||||||
|
|
||||||
|
if (parent_map.hasOwnProperty(elem)) {
|
||||||
|
rv.push(parent_map[elem]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
return select;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function prepare_predicate(next, token) {
|
||||||
|
var tag, key, value, select;
|
||||||
|
token = next();
|
||||||
|
|
||||||
|
if (token[1] === '@') {
|
||||||
|
// attribute
|
||||||
|
token = next();
|
||||||
|
|
||||||
|
if (token[1]) {
|
||||||
|
throw new SyntaxError(token, 'Invalid attribute predicate');
|
||||||
|
}
|
||||||
|
|
||||||
|
key = token[0];
|
||||||
|
token = next();
|
||||||
|
|
||||||
|
if (token[1] === ']') {
|
||||||
|
select = function(context, result) {
|
||||||
|
var i, len, elem, rv = [];
|
||||||
|
|
||||||
|
for (i = 0, len = result.length; i < len; i++) {
|
||||||
|
elem = result[i];
|
||||||
|
|
||||||
|
if (elem.get(key)) {
|
||||||
|
rv.push(elem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else if (token[1] === '=') {
|
||||||
|
value = next()[1];
|
||||||
|
|
||||||
|
if (value[0] === '"' || value[value.length - 1] === '\'') {
|
||||||
|
value = value.slice(1, value.length - 1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new SyntaxError(token, 'Ivalid comparison target');
|
||||||
|
}
|
||||||
|
|
||||||
|
token = next();
|
||||||
|
select = function(context, result) {
|
||||||
|
var i, len, elem, rv = [];
|
||||||
|
|
||||||
|
for (i = 0, len = result.length; i < len; i++) {
|
||||||
|
elem = result[i];
|
||||||
|
|
||||||
|
if (elem.get(key) === value) {
|
||||||
|
rv.push(elem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (token[1] !== ']') {
|
||||||
|
throw new SyntaxError(token, 'Invalid attribute predicate');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!token[1]) {
|
||||||
|
tag = token[0] || '';
|
||||||
|
token = next();
|
||||||
|
|
||||||
|
if (token[1] !== ']') {
|
||||||
|
throw new SyntaxError(token, 'Invalid node predicate');
|
||||||
|
}
|
||||||
|
|
||||||
|
select = function(context, result) {
|
||||||
|
var i, len, elem, rv = [];
|
||||||
|
|
||||||
|
for (i = 0, len = result.length; i < len; i++) {
|
||||||
|
elem = result[i];
|
||||||
|
|
||||||
|
if (elem.find(tag)) {
|
||||||
|
rv.push(elem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new SyntaxError(null, 'Invalid predicate');
|
||||||
|
}
|
||||||
|
|
||||||
|
return select;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var ops = {
|
||||||
|
"": prepare_tag,
|
||||||
|
"*": prepare_star,
|
||||||
|
".": prepare_dot,
|
||||||
|
"..": prepare_dot_dot,
|
||||||
|
"//": prepare_iter,
|
||||||
|
"[": prepare_predicate,
|
||||||
|
};
|
||||||
|
|
||||||
|
function _SelectorContext(root) {
|
||||||
|
this.parent_map = null;
|
||||||
|
this.root = root;
|
||||||
|
}
|
||||||
|
|
||||||
|
function findall(elem, path) {
|
||||||
|
var selector, result, i, len, token, value, select, context;
|
||||||
|
|
||||||
|
if (_cache.hasOwnProperty(path)) {
|
||||||
|
selector = _cache[path];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// TODO: Use smarter cache purging approach
|
||||||
|
if (Object.keys(_cache).length > 100) {
|
||||||
|
_cache = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path.charAt(0) === '/') {
|
||||||
|
throw new SyntaxError(null, 'Cannot use absolute path on element');
|
||||||
|
}
|
||||||
|
|
||||||
|
result = xpath_tokenizer(path);
|
||||||
|
selector = [];
|
||||||
|
|
||||||
|
function getToken() {
|
||||||
|
return result.shift();
|
||||||
|
}
|
||||||
|
|
||||||
|
token = getToken();
|
||||||
|
while (true) {
|
||||||
|
var c = token[1] || '';
|
||||||
|
value = ops[c](getToken, token);
|
||||||
|
|
||||||
|
if (!value) {
|
||||||
|
throw new SyntaxError(null, sprintf('Invalid path: %s', path));
|
||||||
|
}
|
||||||
|
|
||||||
|
selector.push(value);
|
||||||
|
token = getToken();
|
||||||
|
|
||||||
|
if (!token) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (token[1] === '/') {
|
||||||
|
token = getToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!token) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_cache[path] = selector;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute slector pattern
|
||||||
|
result = [elem];
|
||||||
|
context = new _SelectorContext(elem);
|
||||||
|
|
||||||
|
for (i = 0, len = selector.length; i < len; i++) {
|
||||||
|
select = selector[i];
|
||||||
|
result = select(context, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result || [];
|
||||||
|
}
|
||||||
|
|
||||||
|
function find(element, path) {
|
||||||
|
var resultElements = findall(element, path);
|
||||||
|
|
||||||
|
if (resultElements && resultElements.length > 0) {
|
||||||
|
return resultElements[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function findtext(element, path, defvalue) {
|
||||||
|
var resultElements = findall(element, path);
|
||||||
|
|
||||||
|
if (resultElements && resultElements.length > 0) {
|
||||||
|
return resultElements[0].text;
|
||||||
|
}
|
||||||
|
|
||||||
|
return defvalue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
exports.find = find;
|
||||||
|
exports.findall = findall;
|
||||||
|
exports.findtext = findtext;
|
611
node_modules/elementtree/lib/elementtree.js
generated
vendored
Normal file
611
node_modules/elementtree/lib/elementtree.js
generated
vendored
Normal file
@ -0,0 +1,611 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2011 Rackspace
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
var sprintf = require('./sprintf').sprintf;
|
||||||
|
|
||||||
|
var utils = require('./utils');
|
||||||
|
var ElementPath = require('./elementpath');
|
||||||
|
var TreeBuilder = require('./treebuilder').TreeBuilder;
|
||||||
|
var get_parser = require('./parser').get_parser;
|
||||||
|
var constants = require('./constants');
|
||||||
|
|
||||||
|
var element_ids = 0;
|
||||||
|
|
||||||
|
function Element(tag, attrib)
|
||||||
|
{
|
||||||
|
this._id = element_ids++;
|
||||||
|
this.tag = tag;
|
||||||
|
this.attrib = {};
|
||||||
|
this.text = null;
|
||||||
|
this.tail = null;
|
||||||
|
this._children = [];
|
||||||
|
|
||||||
|
if (attrib) {
|
||||||
|
this.attrib = utils.merge(this.attrib, attrib);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Element.prototype.toString = function()
|
||||||
|
{
|
||||||
|
return sprintf("<Element %s at %s>", this.tag, this._id);
|
||||||
|
};
|
||||||
|
|
||||||
|
Element.prototype.makeelement = function(tag, attrib)
|
||||||
|
{
|
||||||
|
return new Element(tag, attrib);
|
||||||
|
};
|
||||||
|
|
||||||
|
Element.prototype.len = function()
|
||||||
|
{
|
||||||
|
return this._children.length;
|
||||||
|
};
|
||||||
|
|
||||||
|
Element.prototype.getItem = function(index)
|
||||||
|
{
|
||||||
|
return this._children[index];
|
||||||
|
};
|
||||||
|
|
||||||
|
Element.prototype.setItem = function(index, element)
|
||||||
|
{
|
||||||
|
this._children[index] = element;
|
||||||
|
};
|
||||||
|
|
||||||
|
Element.prototype.delItem = function(index)
|
||||||
|
{
|
||||||
|
this._children.splice(index, 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
Element.prototype.getSlice = function(start, stop)
|
||||||
|
{
|
||||||
|
return this._children.slice(start, stop);
|
||||||
|
};
|
||||||
|
|
||||||
|
Element.prototype.setSlice = function(start, stop, elements)
|
||||||
|
{
|
||||||
|
var i;
|
||||||
|
var k = 0;
|
||||||
|
for (i = start; i < stop; i++, k++) {
|
||||||
|
this._children[i] = elements[k];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Element.prototype.delSlice = function(start, stop)
|
||||||
|
{
|
||||||
|
this._children.splice(start, stop - start);
|
||||||
|
};
|
||||||
|
|
||||||
|
Element.prototype.append = function(element)
|
||||||
|
{
|
||||||
|
this._children.push(element);
|
||||||
|
};
|
||||||
|
|
||||||
|
Element.prototype.extend = function(elements)
|
||||||
|
{
|
||||||
|
this._children.concat(elements);
|
||||||
|
};
|
||||||
|
|
||||||
|
Element.prototype.insert = function(index, element)
|
||||||
|
{
|
||||||
|
this._children[index] = element;
|
||||||
|
};
|
||||||
|
|
||||||
|
Element.prototype.remove = function(element)
|
||||||
|
{
|
||||||
|
this._children = this._children.filter(function(e) {
|
||||||
|
/* TODO: is this the right way to do this? */
|
||||||
|
if (e._id === element._id) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Element.prototype.getchildren = function() {
|
||||||
|
return this._children;
|
||||||
|
};
|
||||||
|
|
||||||
|
Element.prototype.find = function(path)
|
||||||
|
{
|
||||||
|
return ElementPath.find(this, path);
|
||||||
|
};
|
||||||
|
|
||||||
|
Element.prototype.findtext = function(path, defvalue)
|
||||||
|
{
|
||||||
|
return ElementPath.findtext(this, path, defvalue);
|
||||||
|
};
|
||||||
|
|
||||||
|
Element.prototype.findall = function(path, defvalue)
|
||||||
|
{
|
||||||
|
return ElementPath.findall(this, path, defvalue);
|
||||||
|
};
|
||||||
|
|
||||||
|
Element.prototype.clear = function()
|
||||||
|
{
|
||||||
|
this.attrib = {};
|
||||||
|
this._children = [];
|
||||||
|
this.text = null;
|
||||||
|
this.tail = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
Element.prototype.get = function(key, defvalue)
|
||||||
|
{
|
||||||
|
if (this.attrib[key] !== undefined) {
|
||||||
|
return this.attrib[key];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return defvalue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Element.prototype.set = function(key, value)
|
||||||
|
{
|
||||||
|
this.attrib[key] = value;
|
||||||
|
};
|
||||||
|
|
||||||
|
Element.prototype.keys = function()
|
||||||
|
{
|
||||||
|
return Object.keys(this.attrib);
|
||||||
|
};
|
||||||
|
|
||||||
|
Element.prototype.items = function()
|
||||||
|
{
|
||||||
|
return utils.items(this.attrib);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In python this uses a generator, but in v8 we don't have em,
|
||||||
|
* so we use a callback instead.
|
||||||
|
**/
|
||||||
|
Element.prototype.iter = function(tag, callback)
|
||||||
|
{
|
||||||
|
var self = this;
|
||||||
|
var i, child;
|
||||||
|
|
||||||
|
if (tag === "*") {
|
||||||
|
tag = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tag === null || this.tag === tag) {
|
||||||
|
callback(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < this._children.length; i++) {
|
||||||
|
child = this._children[i];
|
||||||
|
child.iter(tag, function(e) {
|
||||||
|
callback(e);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Element.prototype.itertext = function(callback)
|
||||||
|
{
|
||||||
|
this.iter(null, function(e) {
|
||||||
|
if (e.text) {
|
||||||
|
callback(e.text);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.tail) {
|
||||||
|
callback(e.tail);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
function SubElement(parent, tag, attrib) {
|
||||||
|
var element = parent.makeelement(tag, attrib);
|
||||||
|
parent.append(element);
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Comment(text) {
|
||||||
|
var element = new Element(Comment);
|
||||||
|
if (text) {
|
||||||
|
element.text = text;
|
||||||
|
}
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
function CData(text) {
|
||||||
|
var element = new Element(CData);
|
||||||
|
if (text) {
|
||||||
|
element.text = text;
|
||||||
|
}
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
function ProcessingInstruction(target, text)
|
||||||
|
{
|
||||||
|
var element = new Element(ProcessingInstruction);
|
||||||
|
element.text = target;
|
||||||
|
if (text) {
|
||||||
|
element.text = element.text + " " + text;
|
||||||
|
}
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
function QName(text_or_uri, tag)
|
||||||
|
{
|
||||||
|
if (tag) {
|
||||||
|
text_or_uri = sprintf("{%s}%s", text_or_uri, tag);
|
||||||
|
}
|
||||||
|
this.text = text_or_uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
QName.prototype.toString = function() {
|
||||||
|
return this.text;
|
||||||
|
};
|
||||||
|
|
||||||
|
function ElementTree(element)
|
||||||
|
{
|
||||||
|
this._root = element;
|
||||||
|
}
|
||||||
|
|
||||||
|
ElementTree.prototype.getroot = function() {
|
||||||
|
return this._root;
|
||||||
|
};
|
||||||
|
|
||||||
|
ElementTree.prototype._setroot = function(element) {
|
||||||
|
this._root = element;
|
||||||
|
};
|
||||||
|
|
||||||
|
ElementTree.prototype.parse = function(source, parser) {
|
||||||
|
if (!parser) {
|
||||||
|
parser = get_parser(constants.DEFAULT_PARSER);
|
||||||
|
parser = new parser.XMLParser(new TreeBuilder());
|
||||||
|
}
|
||||||
|
|
||||||
|
parser.feed(source);
|
||||||
|
this._root = parser.close();
|
||||||
|
return this._root;
|
||||||
|
};
|
||||||
|
|
||||||
|
ElementTree.prototype.iter = function(tag, callback) {
|
||||||
|
this._root.iter(tag, callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
ElementTree.prototype.find = function(path) {
|
||||||
|
return this._root.find(path);
|
||||||
|
};
|
||||||
|
|
||||||
|
ElementTree.prototype.findtext = function(path, defvalue) {
|
||||||
|
return this._root.findtext(path, defvalue);
|
||||||
|
};
|
||||||
|
|
||||||
|
ElementTree.prototype.findall = function(path) {
|
||||||
|
return this._root.findall(path);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unlike ElementTree, we don't write to a file, we return you a string.
|
||||||
|
*/
|
||||||
|
ElementTree.prototype.write = function(options) {
|
||||||
|
var sb = [];
|
||||||
|
options = utils.merge({
|
||||||
|
encoding: 'utf-8',
|
||||||
|
xml_declaration: null,
|
||||||
|
default_namespace: null,
|
||||||
|
method: 'xml'}, options);
|
||||||
|
|
||||||
|
if (options.xml_declaration !== false) {
|
||||||
|
sb.push("<?xml version='1.0' encoding='"+options.encoding +"'?>\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.method === "text") {
|
||||||
|
_serialize_text(sb, self._root, encoding);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var qnames, namespaces, indent, indent_string;
|
||||||
|
var x = _namespaces(this._root, options.encoding, options.default_namespace);
|
||||||
|
qnames = x[0];
|
||||||
|
namespaces = x[1];
|
||||||
|
|
||||||
|
if (options.hasOwnProperty('indent')) {
|
||||||
|
indent = 0;
|
||||||
|
indent_string = new Array(options.indent + 1).join(' ');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
indent = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.method === "xml") {
|
||||||
|
_serialize_xml(function(data) {
|
||||||
|
sb.push(data);
|
||||||
|
}, this._root, options.encoding, qnames, namespaces, indent, indent_string);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* TODO: html */
|
||||||
|
throw new Error("unknown serialization method "+ options.method);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.join("");
|
||||||
|
};
|
||||||
|
|
||||||
|
var _namespace_map = {
|
||||||
|
/* "well-known" namespace prefixes */
|
||||||
|
"http://www.w3.org/XML/1998/namespace": "xml",
|
||||||
|
"http://www.w3.org/1999/xhtml": "html",
|
||||||
|
"http://www.w3.org/1999/02/22-rdf-syntax-ns#": "rdf",
|
||||||
|
"http://schemas.xmlsoap.org/wsdl/": "wsdl",
|
||||||
|
/* xml schema */
|
||||||
|
"http://www.w3.org/2001/XMLSchema": "xs",
|
||||||
|
"http://www.w3.org/2001/XMLSchema-instance": "xsi",
|
||||||
|
/* dublic core */
|
||||||
|
"http://purl.org/dc/elements/1.1/": "dc",
|
||||||
|
};
|
||||||
|
|
||||||
|
function register_namespace(prefix, uri) {
|
||||||
|
if (/ns\d+$/.test(prefix)) {
|
||||||
|
throw new Error('Prefix format reserved for internal use');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_namespace_map.hasOwnProperty(uri) && _namespace_map[uri] === prefix) {
|
||||||
|
delete _namespace_map[uri];
|
||||||
|
}
|
||||||
|
|
||||||
|
_namespace_map[uri] = prefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function _escape(text, encoding, isAttribute, isText) {
|
||||||
|
if (text) {
|
||||||
|
text = text.toString();
|
||||||
|
text = text.replace(/&/g, '&');
|
||||||
|
text = text.replace(/</g, '<');
|
||||||
|
text = text.replace(/>/g, '>');
|
||||||
|
if (!isText) {
|
||||||
|
text = text.replace(/\n/g, '
');
|
||||||
|
text = text.replace(/\r/g, '
');
|
||||||
|
}
|
||||||
|
if (isAttribute) {
|
||||||
|
text = text.replace(/"/g, '"');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: benchmark single regex */
|
||||||
|
function _escape_attrib(text, encoding) {
|
||||||
|
return _escape(text, encoding, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _escape_cdata(text, encoding) {
|
||||||
|
return _escape(text, encoding, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _escape_text(text, encoding) {
|
||||||
|
return _escape(text, encoding, false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _namespaces(elem, encoding, default_namespace) {
|
||||||
|
var qnames = {};
|
||||||
|
var namespaces = {};
|
||||||
|
|
||||||
|
if (default_namespace) {
|
||||||
|
namespaces[default_namespace] = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
function encode(text) {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
function add_qname(qname) {
|
||||||
|
if (qname[0] === "{") {
|
||||||
|
var tmp = qname.substring(1).split("}", 2);
|
||||||
|
var uri = tmp[0];
|
||||||
|
var tag = tmp[1];
|
||||||
|
var prefix = namespaces[uri];
|
||||||
|
|
||||||
|
if (prefix === undefined) {
|
||||||
|
prefix = _namespace_map[uri];
|
||||||
|
if (prefix === undefined) {
|
||||||
|
prefix = "ns" + Object.keys(namespaces).length;
|
||||||
|
}
|
||||||
|
if (prefix !== "xml") {
|
||||||
|
namespaces[uri] = prefix;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prefix) {
|
||||||
|
qnames[qname] = sprintf("%s:%s", prefix, tag);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
qnames[qname] = tag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (default_namespace) {
|
||||||
|
throw new Error('cannot use non-qualified names with default_namespace option');
|
||||||
|
}
|
||||||
|
|
||||||
|
qnames[qname] = qname;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
elem.iter(null, function(e) {
|
||||||
|
var i;
|
||||||
|
var tag = e.tag;
|
||||||
|
var text = e.text;
|
||||||
|
var items = e.items();
|
||||||
|
|
||||||
|
if (tag instanceof QName && qnames[tag.text] === undefined) {
|
||||||
|
add_qname(tag.text);
|
||||||
|
}
|
||||||
|
else if (typeof(tag) === "string") {
|
||||||
|
add_qname(tag);
|
||||||
|
}
|
||||||
|
else if (tag !== null && tag !== Comment && tag !== CData && tag !== ProcessingInstruction) {
|
||||||
|
throw new Error('Invalid tag type for serialization: '+ tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (text instanceof QName && qnames[text.text] === undefined) {
|
||||||
|
add_qname(text.text);
|
||||||
|
}
|
||||||
|
|
||||||
|
items.forEach(function(item) {
|
||||||
|
var key = item[0],
|
||||||
|
value = item[1];
|
||||||
|
if (key instanceof QName) {
|
||||||
|
key = key.text;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qnames[key] === undefined) {
|
||||||
|
add_qname(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value instanceof QName && qnames[value.text] === undefined) {
|
||||||
|
add_qname(value.text);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return [qnames, namespaces];
|
||||||
|
}
|
||||||
|
|
||||||
|
function _serialize_xml(write, elem, encoding, qnames, namespaces, indent, indent_string) {
|
||||||
|
var tag = elem.tag;
|
||||||
|
var text = elem.text;
|
||||||
|
var items;
|
||||||
|
var i;
|
||||||
|
|
||||||
|
var newlines = indent || (indent === 0);
|
||||||
|
write(Array(indent + 1).join(indent_string));
|
||||||
|
|
||||||
|
if (tag === Comment) {
|
||||||
|
write(sprintf("<!--%s-->", _escape_cdata(text, encoding)));
|
||||||
|
}
|
||||||
|
else if (tag === ProcessingInstruction) {
|
||||||
|
write(sprintf("<?%s?>", _escape_cdata(text, encoding)));
|
||||||
|
}
|
||||||
|
else if (tag === CData) {
|
||||||
|
text = text || '';
|
||||||
|
write(sprintf("<![CDATA[%s]]>", text));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
tag = qnames[tag];
|
||||||
|
if (tag === undefined) {
|
||||||
|
if (text) {
|
||||||
|
write(_escape_text(text, encoding));
|
||||||
|
}
|
||||||
|
elem.iter(function(e) {
|
||||||
|
_serialize_xml(write, e, encoding, qnames, null, newlines ? indent + 1 : false, indent_string);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
write("<" + tag);
|
||||||
|
items = elem.items();
|
||||||
|
|
||||||
|
if (items || namespaces) {
|
||||||
|
items.sort(); // lexical order
|
||||||
|
|
||||||
|
items.forEach(function(item) {
|
||||||
|
var k = item[0],
|
||||||
|
v = item[1];
|
||||||
|
|
||||||
|
if (k instanceof QName) {
|
||||||
|
k = k.text;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v instanceof QName) {
|
||||||
|
v = qnames[v.text];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
v = _escape_attrib(v, encoding);
|
||||||
|
}
|
||||||
|
write(sprintf(" %s=\"%s\"", qnames[k], v));
|
||||||
|
});
|
||||||
|
|
||||||
|
if (namespaces) {
|
||||||
|
items = utils.items(namespaces);
|
||||||
|
items.sort(function(a, b) { return a[1] < b[1]; });
|
||||||
|
|
||||||
|
items.forEach(function(item) {
|
||||||
|
var k = item[1],
|
||||||
|
v = item[0];
|
||||||
|
|
||||||
|
if (k) {
|
||||||
|
k = ':' + k;
|
||||||
|
}
|
||||||
|
|
||||||
|
write(sprintf(" xmlns%s=\"%s\"", k, _escape_attrib(v, encoding)));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (text || elem.len()) {
|
||||||
|
if (text && text.toString().match(/^\s*$/)) {
|
||||||
|
text = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
write(">");
|
||||||
|
if (!text && newlines) {
|
||||||
|
write("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (text) {
|
||||||
|
write(_escape_text(text, encoding));
|
||||||
|
}
|
||||||
|
elem._children.forEach(function(e) {
|
||||||
|
_serialize_xml(write, e, encoding, qnames, null, newlines ? indent + 1 : false, indent_string);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!text && indent) {
|
||||||
|
write(Array(indent + 1).join(indent_string));
|
||||||
|
}
|
||||||
|
write("</" + tag + ">");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
write(" />");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newlines) {
|
||||||
|
write("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function parse(source, parser) {
|
||||||
|
var tree = new ElementTree();
|
||||||
|
tree.parse(source, parser);
|
||||||
|
return tree;
|
||||||
|
}
|
||||||
|
|
||||||
|
function tostring(element, options) {
|
||||||
|
return new ElementTree(element).write(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.PI = ProcessingInstruction;
|
||||||
|
exports.Comment = Comment;
|
||||||
|
exports.CData = CData;
|
||||||
|
exports.ProcessingInstruction = ProcessingInstruction;
|
||||||
|
exports.SubElement = SubElement;
|
||||||
|
exports.QName = QName;
|
||||||
|
exports.ElementTree = ElementTree;
|
||||||
|
exports.ElementPath = ElementPath;
|
||||||
|
exports.Element = function(tag, attrib) {
|
||||||
|
return new Element(tag, attrib);
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.XML = function(data) {
|
||||||
|
var et = new ElementTree();
|
||||||
|
return et.parse(data);
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.parse = parse;
|
||||||
|
exports.register_namespace = register_namespace;
|
||||||
|
exports.tostring = tostring;
|
31
node_modules/elementtree/lib/errors.js
generated
vendored
Normal file
31
node_modules/elementtree/lib/errors.js
generated
vendored
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2011 Rackspace
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
var util = require('util');
|
||||||
|
|
||||||
|
var sprintf = require('./sprintf').sprintf;
|
||||||
|
|
||||||
|
function SyntaxError(token, msg) {
|
||||||
|
msg = msg || sprintf('Syntax Error at token %s', token.toString());
|
||||||
|
this.token = token;
|
||||||
|
this.message = msg;
|
||||||
|
Error.call(this, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
util.inherits(SyntaxError, Error);
|
||||||
|
|
||||||
|
exports.SyntaxError = SyntaxError;
|
33
node_modules/elementtree/lib/parser.js
generated
vendored
Normal file
33
node_modules/elementtree/lib/parser.js
generated
vendored
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011 Rackspace
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* TODO: support node-expat C++ module optionally */
|
||||||
|
|
||||||
|
var util = require('util');
|
||||||
|
var parsers = require('./parsers/index');
|
||||||
|
|
||||||
|
function get_parser(name) {
|
||||||
|
if (name === 'sax') {
|
||||||
|
return parsers.sax;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new Error('Invalid parser: ' + name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
exports.get_parser = get_parser;
|
1
node_modules/elementtree/lib/parsers/index.js
generated
vendored
Normal file
1
node_modules/elementtree/lib/parsers/index.js
generated
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
exports.sax = require('./sax');
|
56
node_modules/elementtree/lib/parsers/sax.js
generated
vendored
Normal file
56
node_modules/elementtree/lib/parsers/sax.js
generated
vendored
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
var util = require('util');
|
||||||
|
|
||||||
|
var sax = require('sax');
|
||||||
|
|
||||||
|
var TreeBuilder = require('./../treebuilder').TreeBuilder;
|
||||||
|
|
||||||
|
function XMLParser(target) {
|
||||||
|
this.parser = sax.parser(true);
|
||||||
|
|
||||||
|
this.target = (target) ? target : new TreeBuilder();
|
||||||
|
|
||||||
|
this.parser.onopentag = this._handleOpenTag.bind(this);
|
||||||
|
this.parser.ontext = this._handleText.bind(this);
|
||||||
|
this.parser.oncdata = this._handleCdata.bind(this);
|
||||||
|
this.parser.ondoctype = this._handleDoctype.bind(this);
|
||||||
|
this.parser.oncomment = this._handleComment.bind(this);
|
||||||
|
this.parser.onclosetag = this._handleCloseTag.bind(this);
|
||||||
|
this.parser.onerror = this._handleError.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
XMLParser.prototype._handleOpenTag = function(tag) {
|
||||||
|
this.target.start(tag.name, tag.attributes);
|
||||||
|
};
|
||||||
|
|
||||||
|
XMLParser.prototype._handleText = function(text) {
|
||||||
|
this.target.data(text);
|
||||||
|
};
|
||||||
|
|
||||||
|
XMLParser.prototype._handleCdata = function(text) {
|
||||||
|
this.target.data(text);
|
||||||
|
};
|
||||||
|
|
||||||
|
XMLParser.prototype._handleDoctype = function(text) {
|
||||||
|
};
|
||||||
|
|
||||||
|
XMLParser.prototype._handleComment = function(comment) {
|
||||||
|
};
|
||||||
|
|
||||||
|
XMLParser.prototype._handleCloseTag = function(tag) {
|
||||||
|
this.target.end(tag);
|
||||||
|
};
|
||||||
|
|
||||||
|
XMLParser.prototype._handleError = function(err) {
|
||||||
|
throw err;
|
||||||
|
};
|
||||||
|
|
||||||
|
XMLParser.prototype.feed = function(chunk) {
|
||||||
|
this.parser.write(chunk);
|
||||||
|
};
|
||||||
|
|
||||||
|
XMLParser.prototype.close = function() {
|
||||||
|
this.parser.close();
|
||||||
|
return this.target.close();
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.XMLParser = XMLParser;
|
86
node_modules/elementtree/lib/sprintf.js
generated
vendored
Normal file
86
node_modules/elementtree/lib/sprintf.js
generated
vendored
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011 Rackspace
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
var cache = {};
|
||||||
|
|
||||||
|
|
||||||
|
// Do any others need escaping?
|
||||||
|
var TO_ESCAPE = {
|
||||||
|
'\'': '\\\'',
|
||||||
|
'\n': '\\n'
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
function populate(formatter) {
|
||||||
|
var i, type,
|
||||||
|
key = formatter,
|
||||||
|
prev = 0,
|
||||||
|
arg = 1,
|
||||||
|
builder = 'return \'';
|
||||||
|
|
||||||
|
for (i = 0; i < formatter.length; i++) {
|
||||||
|
if (formatter[i] === '%') {
|
||||||
|
type = formatter[i + 1];
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case 's':
|
||||||
|
builder += formatter.slice(prev, i) + '\' + arguments[' + arg + '] + \'';
|
||||||
|
prev = i + 2;
|
||||||
|
arg++;
|
||||||
|
break;
|
||||||
|
case 'j':
|
||||||
|
builder += formatter.slice(prev, i) + '\' + JSON.stringify(arguments[' + arg + ']) + \'';
|
||||||
|
prev = i + 2;
|
||||||
|
arg++;
|
||||||
|
break;
|
||||||
|
case '%':
|
||||||
|
builder += formatter.slice(prev, i + 1);
|
||||||
|
prev = i + 2;
|
||||||
|
i++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} else if (TO_ESCAPE[formatter[i]]) {
|
||||||
|
builder += formatter.slice(prev, i) + TO_ESCAPE[formatter[i]];
|
||||||
|
prev = i + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
builder += formatter.slice(prev) + '\';';
|
||||||
|
cache[key] = new Function(builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A fast version of sprintf(), which currently only supports the %s and %j.
|
||||||
|
* This caches a formatting function for each format string that is used, so
|
||||||
|
* you should only use this sprintf() will be called many times with a single
|
||||||
|
* format string and a limited number of format strings will ever be used (in
|
||||||
|
* general this means that format strings should be string literals).
|
||||||
|
*
|
||||||
|
* @param {String} formatter A format string.
|
||||||
|
* @param {...String} var_args Values that will be formatted by %s and %j.
|
||||||
|
* @return {String} The formatted output.
|
||||||
|
*/
|
||||||
|
exports.sprintf = function(formatter, var_args) {
|
||||||
|
if (!cache[formatter]) {
|
||||||
|
populate(formatter);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cache[formatter].apply(null, arguments);
|
||||||
|
};
|
60
node_modules/elementtree/lib/treebuilder.js
generated
vendored
Normal file
60
node_modules/elementtree/lib/treebuilder.js
generated
vendored
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
function TreeBuilder(element_factory) {
|
||||||
|
this._data = [];
|
||||||
|
this._elem = [];
|
||||||
|
this._last = null;
|
||||||
|
this._tail = null;
|
||||||
|
if (!element_factory) {
|
||||||
|
/* evil circular dep */
|
||||||
|
element_factory = require('./elementtree').Element;
|
||||||
|
}
|
||||||
|
this._factory = element_factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
TreeBuilder.prototype.close = function() {
|
||||||
|
return this._last;
|
||||||
|
};
|
||||||
|
|
||||||
|
TreeBuilder.prototype._flush = function() {
|
||||||
|
if (this._data) {
|
||||||
|
if (this._last !== null) {
|
||||||
|
var text = this._data.join("");
|
||||||
|
if (this._tail) {
|
||||||
|
this._last.tail = text;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this._last.text = text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this._data = [];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TreeBuilder.prototype.data = function(data) {
|
||||||
|
this._data.push(data);
|
||||||
|
};
|
||||||
|
|
||||||
|
TreeBuilder.prototype.start = function(tag, attrs) {
|
||||||
|
this._flush();
|
||||||
|
var elem = this._factory(tag, attrs);
|
||||||
|
this._last = elem;
|
||||||
|
|
||||||
|
if (this._elem.length) {
|
||||||
|
this._elem[this._elem.length - 1].append(elem);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._elem.push(elem);
|
||||||
|
|
||||||
|
this._tail = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
TreeBuilder.prototype.end = function(tag) {
|
||||||
|
this._flush();
|
||||||
|
this._last = this._elem.pop();
|
||||||
|
if (this._last.tag !== tag) {
|
||||||
|
throw new Error("end tag mismatch");
|
||||||
|
}
|
||||||
|
this._tail = 1;
|
||||||
|
return this._last;
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.TreeBuilder = TreeBuilder;
|
72
node_modules/elementtree/lib/utils.js
generated
vendored
Normal file
72
node_modules/elementtree/lib/utils.js
generated
vendored
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2011 Rackspace
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Object} hash.
|
||||||
|
* @param {Array} ignored.
|
||||||
|
*/
|
||||||
|
function items(hash, ignored) {
|
||||||
|
ignored = ignored || null;
|
||||||
|
var k, rv = [];
|
||||||
|
|
||||||
|
function is_ignored(key) {
|
||||||
|
if (!ignored || ignored.length === 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ignored.indexOf(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (k in hash) {
|
||||||
|
if (hash.hasOwnProperty(k) && !(is_ignored(ignored))) {
|
||||||
|
rv.push([k, hash[k]]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function findall(re, str) {
|
||||||
|
var match, matches = [];
|
||||||
|
|
||||||
|
while ((match = re.exec(str))) {
|
||||||
|
matches.push(match);
|
||||||
|
}
|
||||||
|
|
||||||
|
return matches;
|
||||||
|
}
|
||||||
|
|
||||||
|
function merge(a, b) {
|
||||||
|
var c = {}, attrname;
|
||||||
|
|
||||||
|
for (attrname in a) {
|
||||||
|
if (a.hasOwnProperty(attrname)) {
|
||||||
|
c[attrname] = a[attrname];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (attrname in b) {
|
||||||
|
if (b.hasOwnProperty(attrname)) {
|
||||||
|
c[attrname] = b[attrname];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.items = items;
|
||||||
|
exports.findall = findall;
|
||||||
|
exports.merge = merge;
|
9
node_modules/elementtree/node_modules/sax/AUTHORS
generated
vendored
Normal file
9
node_modules/elementtree/node_modules/sax/AUTHORS
generated
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# contributors sorted by whether or not they're me.
|
||||||
|
Isaac Z. Schlueter <i@izs.me>
|
||||||
|
Stein Martin Hustad <stein@hustad.com>
|
||||||
|
Mikeal Rogers <mikeal.rogers@gmail.com>
|
||||||
|
Laurie Harper <laurie@holoweb.net>
|
||||||
|
Jann Horn <jann@Jann-PC.fritz.box>
|
||||||
|
Elijah Insua <tmpvar@gmail.com>
|
||||||
|
Henry Rawas <henryr@schakra.com>
|
||||||
|
Justin Makeig <jmpublic@makeig.com>
|
0
bin/node_modules/nopt/LICENSE → node_modules/elementtree/node_modules/sax/LICENSE
generated
vendored
0
bin/node_modules/nopt/LICENSE → node_modules/elementtree/node_modules/sax/LICENSE
generated
vendored
213
node_modules/elementtree/node_modules/sax/README.md
generated
vendored
Normal file
213
node_modules/elementtree/node_modules/sax/README.md
generated
vendored
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
# sax js
|
||||||
|
|
||||||
|
A sax-style parser for XML and HTML.
|
||||||
|
|
||||||
|
Designed with [node](http://nodejs.org/) in mind, but should work fine in
|
||||||
|
the browser or other CommonJS implementations.
|
||||||
|
|
||||||
|
## What This Is
|
||||||
|
|
||||||
|
* A very simple tool to parse through an XML string.
|
||||||
|
* A stepping stone to a streaming HTML parser.
|
||||||
|
* A handy way to deal with RSS and other mostly-ok-but-kinda-broken XML
|
||||||
|
docs.
|
||||||
|
|
||||||
|
## What This Is (probably) Not
|
||||||
|
|
||||||
|
* An HTML Parser - That's a fine goal, but this isn't it. It's just
|
||||||
|
XML.
|
||||||
|
* A DOM Builder - You can use it to build an object model out of XML,
|
||||||
|
but it doesn't do that out of the box.
|
||||||
|
* XSLT - No DOM = no querying.
|
||||||
|
* 100% Compliant with (some other SAX implementation) - Most SAX
|
||||||
|
implementations are in Java and do a lot more than this does.
|
||||||
|
* An XML Validator - It does a little validation when in strict mode, but
|
||||||
|
not much.
|
||||||
|
* A Schema-Aware XSD Thing - Schemas are an exercise in fetishistic
|
||||||
|
masochism.
|
||||||
|
* A DTD-aware Thing - Fetching DTDs is a much bigger job.
|
||||||
|
|
||||||
|
## Regarding `<!DOCTYPE`s and `<!ENTITY`s
|
||||||
|
|
||||||
|
The parser will handle the basic XML entities in text nodes and attribute
|
||||||
|
values: `& < > ' "`. It's possible to define additional
|
||||||
|
entities in XML by putting them in the DTD. This parser doesn't do anything
|
||||||
|
with that. If you want to listen to the `ondoctype` event, and then fetch
|
||||||
|
the doctypes, and read the entities and add them to `parser.ENTITIES`, then
|
||||||
|
be my guest.
|
||||||
|
|
||||||
|
Unknown entities will fail in strict mode, and in loose mode, will pass
|
||||||
|
through unmolested.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
var sax = require("./lib/sax"),
|
||||||
|
strict = true, // set to false for html-mode
|
||||||
|
parser = sax.parser(strict);
|
||||||
|
|
||||||
|
parser.onerror = function (e) {
|
||||||
|
// an error happened.
|
||||||
|
};
|
||||||
|
parser.ontext = function (t) {
|
||||||
|
// got some text. t is the string of text.
|
||||||
|
};
|
||||||
|
parser.onopentag = function (node) {
|
||||||
|
// opened a tag. node has "name" and "attributes"
|
||||||
|
};
|
||||||
|
parser.onattribute = function (attr) {
|
||||||
|
// an attribute. attr has "name" and "value"
|
||||||
|
};
|
||||||
|
parser.onend = function () {
|
||||||
|
// parser stream is done, and ready to have more stuff written to it.
|
||||||
|
};
|
||||||
|
|
||||||
|
parser.write('<xml>Hello, <who name="world">world</who>!</xml>').close();
|
||||||
|
|
||||||
|
// stream usage
|
||||||
|
// takes the same options as the parser
|
||||||
|
var saxStream = require("sax").createStream(strict, options)
|
||||||
|
saxStream.on("error", function (e) {
|
||||||
|
// unhandled errors will throw, since this is a proper node
|
||||||
|
// event emitter.
|
||||||
|
console.error("error!", e)
|
||||||
|
// clear the error
|
||||||
|
this._parser.error = null
|
||||||
|
this._parser.resume()
|
||||||
|
})
|
||||||
|
saxStream.on("opentag", function (node) {
|
||||||
|
// same object as above
|
||||||
|
})
|
||||||
|
// pipe is supported, and it's readable/writable
|
||||||
|
// same chunks coming in also go out.
|
||||||
|
fs.createReadStream("file.xml")
|
||||||
|
.pipe(saxStream)
|
||||||
|
.pipe(fs.createReadStream("file-copy.xml"))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Arguments
|
||||||
|
|
||||||
|
Pass the following arguments to the parser function. All are optional.
|
||||||
|
|
||||||
|
`strict` - Boolean. Whether or not to be a jerk. Default: `false`.
|
||||||
|
|
||||||
|
`opt` - Object bag of settings regarding string formatting. All default to `false`.
|
||||||
|
|
||||||
|
Settings supported:
|
||||||
|
|
||||||
|
* `trim` - Boolean. Whether or not to trim text and comment nodes.
|
||||||
|
* `normalize` - Boolean. If true, then turn any whitespace into a single
|
||||||
|
space.
|
||||||
|
* `lowercasetags` - Boolean. If true, then lowercase tags in loose mode,
|
||||||
|
rather than uppercasing them.
|
||||||
|
* `xmlns` - Boolean. If true, then namespaces are supported.
|
||||||
|
|
||||||
|
## Methods
|
||||||
|
|
||||||
|
`write` - Write bytes onto the stream. You don't have to do this all at
|
||||||
|
once. You can keep writing as much as you want.
|
||||||
|
|
||||||
|
`close` - Close the stream. Once closed, no more data may be written until
|
||||||
|
it is done processing the buffer, which is signaled by the `end` event.
|
||||||
|
|
||||||
|
`resume` - To gracefully handle errors, assign a listener to the `error`
|
||||||
|
event. Then, when the error is taken care of, you can call `resume` to
|
||||||
|
continue parsing. Otherwise, the parser will not continue while in an error
|
||||||
|
state.
|
||||||
|
|
||||||
|
## Members
|
||||||
|
|
||||||
|
At all times, the parser object will have the following members:
|
||||||
|
|
||||||
|
`line`, `column`, `position` - Indications of the position in the XML
|
||||||
|
document where the parser currently is looking.
|
||||||
|
|
||||||
|
`startTagPosition` - Indicates the position where the current tag starts.
|
||||||
|
|
||||||
|
`closed` - Boolean indicating whether or not the parser can be written to.
|
||||||
|
If it's `true`, then wait for the `ready` event to write again.
|
||||||
|
|
||||||
|
`strict` - Boolean indicating whether or not the parser is a jerk.
|
||||||
|
|
||||||
|
`opt` - Any options passed into the constructor.
|
||||||
|
|
||||||
|
`tag` - The current tag being dealt with.
|
||||||
|
|
||||||
|
And a bunch of other stuff that you probably shouldn't touch.
|
||||||
|
|
||||||
|
## Events
|
||||||
|
|
||||||
|
All events emit with a single argument. To listen to an event, assign a
|
||||||
|
function to `on<eventname>`. Functions get executed in the this-context of
|
||||||
|
the parser object. The list of supported events are also in the exported
|
||||||
|
`EVENTS` array.
|
||||||
|
|
||||||
|
When using the stream interface, assign handlers using the EventEmitter
|
||||||
|
`on` function in the normal fashion.
|
||||||
|
|
||||||
|
`error` - Indication that something bad happened. The error will be hanging
|
||||||
|
out on `parser.error`, and must be deleted before parsing can continue. By
|
||||||
|
listening to this event, you can keep an eye on that kind of stuff. Note:
|
||||||
|
this happens *much* more in strict mode. Argument: instance of `Error`.
|
||||||
|
|
||||||
|
`text` - Text node. Argument: string of text.
|
||||||
|
|
||||||
|
`doctype` - The `<!DOCTYPE` declaration. Argument: doctype string.
|
||||||
|
|
||||||
|
`processinginstruction` - Stuff like `<?xml foo="blerg" ?>`. Argument:
|
||||||
|
object with `name` and `body` members. Attributes are not parsed, as
|
||||||
|
processing instructions have implementation dependent semantics.
|
||||||
|
|
||||||
|
`sgmldeclaration` - Random SGML declarations. Stuff like `<!ENTITY p>`
|
||||||
|
would trigger this kind of event. This is a weird thing to support, so it
|
||||||
|
might go away at some point. SAX isn't intended to be used to parse SGML,
|
||||||
|
after all.
|
||||||
|
|
||||||
|
`opentag` - An opening tag. Argument: object with `name` and `attributes`.
|
||||||
|
In non-strict mode, tag names are uppercased, unless the `lowercasetags`
|
||||||
|
option is set. If the `xmlns` option is set, then it will contain
|
||||||
|
namespace binding information on the `ns` member, and will have a
|
||||||
|
`local`, `prefix`, and `uri` member.
|
||||||
|
|
||||||
|
`closetag` - A closing tag. In loose mode, tags are auto-closed if their
|
||||||
|
parent closes. In strict mode, well-formedness is enforced. Note that
|
||||||
|
self-closing tags will have `closeTag` emitted immediately after `openTag`.
|
||||||
|
Argument: tag name.
|
||||||
|
|
||||||
|
`attribute` - An attribute node. Argument: object with `name` and `value`,
|
||||||
|
and also namespace information if the `xmlns` option flag is set.
|
||||||
|
|
||||||
|
`comment` - A comment node. Argument: the string of the comment.
|
||||||
|
|
||||||
|
`opencdata` - The opening tag of a `<![CDATA[` block.
|
||||||
|
|
||||||
|
`cdata` - The text of a `<![CDATA[` block. Since `<![CDATA[` blocks can get
|
||||||
|
quite large, this event may fire multiple times for a single block, if it
|
||||||
|
is broken up into multiple `write()`s. Argument: the string of random
|
||||||
|
character data.
|
||||||
|
|
||||||
|
`closecdata` - The closing tag (`]]>`) of a `<![CDATA[` block.
|
||||||
|
|
||||||
|
`opennamespace` - If the `xmlns` option is set, then this event will
|
||||||
|
signal the start of a new namespace binding.
|
||||||
|
|
||||||
|
`closenamespace` - If the `xmlns` option is set, then this event will
|
||||||
|
signal the end of a namespace binding.
|
||||||
|
|
||||||
|
`end` - Indication that the closed stream has ended.
|
||||||
|
|
||||||
|
`ready` - Indication that the stream has reset, and is ready to be written
|
||||||
|
to.
|
||||||
|
|
||||||
|
`noscript` - In non-strict mode, `<script>` tags trigger a `"script"`
|
||||||
|
event, and their contents are not checked for special xml characters.
|
||||||
|
If you pass `noscript: true`, then this behavior is suppressed.
|
||||||
|
|
||||||
|
## Reporting Problems
|
||||||
|
|
||||||
|
It's best to write a failing test if you find an issue. I will always
|
||||||
|
accept pull requests with failing tests if they demonstrate intended
|
||||||
|
behavior, but it is very hard to figure out what issue you're describing
|
||||||
|
without a test. Writing a test is also the best way for you yourself
|
||||||
|
to figure out if you really understand the issue you think you have with
|
||||||
|
sax-js.
|
1006
node_modules/elementtree/node_modules/sax/lib/sax.js
generated
vendored
Normal file
1006
node_modules/elementtree/node_modules/sax/lib/sax.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
89
node_modules/elementtree/node_modules/sax/package.json
generated
vendored
Normal file
89
node_modules/elementtree/node_modules/sax/package.json
generated
vendored
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
{
|
||||||
|
"name": "sax",
|
||||||
|
"description": "An evented streaming XML parser in JavaScript",
|
||||||
|
"author": {
|
||||||
|
"name": "Isaac Z. Schlueter",
|
||||||
|
"email": "i@izs.me",
|
||||||
|
"url": "http://blog.izs.me/"
|
||||||
|
},
|
||||||
|
"version": "0.3.5",
|
||||||
|
"main": "lib/sax.js",
|
||||||
|
"license": {
|
||||||
|
"type": "MIT",
|
||||||
|
"url": "https://raw.github.com/isaacs/sax-js/master/LICENSE"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"test": "node test/index.js"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git://github.com/isaacs/sax-js.git"
|
||||||
|
},
|
||||||
|
"_npmUser": {
|
||||||
|
"name": "isaacs",
|
||||||
|
"email": "i@izs.me"
|
||||||
|
},
|
||||||
|
"_id": "sax@0.3.5",
|
||||||
|
"contributors": [
|
||||||
|
{
|
||||||
|
"name": "Isaac Z. Schlueter",
|
||||||
|
"email": "i@izs.me"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Stein Martin Hustad",
|
||||||
|
"email": "stein@hustad.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Mikeal Rogers",
|
||||||
|
"email": "mikeal.rogers@gmail.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Laurie Harper",
|
||||||
|
"email": "laurie@holoweb.net"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Jann Horn",
|
||||||
|
"email": "jann@Jann-PC.fritz.box"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Elijah Insua",
|
||||||
|
"email": "tmpvar@gmail.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Henry Rawas",
|
||||||
|
"email": "henryr@schakra.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Justin Makeig",
|
||||||
|
"email": "jmpublic@makeig.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dependencies": {},
|
||||||
|
"devDependencies": {},
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
},
|
||||||
|
"_engineSupported": true,
|
||||||
|
"_npmVersion": "1.1.0-beta-7",
|
||||||
|
"_nodeVersion": "v0.6.7-pre",
|
||||||
|
"_defaultsLoaded": true,
|
||||||
|
"dist": {
|
||||||
|
"shasum": "88fcfc1f73c0c8bbd5b7c776b6d3f3501eed073d",
|
||||||
|
"tarball": "http://registry.npmjs.org/sax/-/sax-0.3.5.tgz"
|
||||||
|
},
|
||||||
|
"maintainers": [
|
||||||
|
{
|
||||||
|
"name": "isaacs",
|
||||||
|
"email": "i@izs.me"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"directories": {},
|
||||||
|
"_shasum": "88fcfc1f73c0c8bbd5b7c776b6d3f3501eed073d",
|
||||||
|
"_resolved": "https://registry.npmjs.org/sax/-/sax-0.3.5.tgz",
|
||||||
|
"_from": "sax@0.3.5",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/isaacs/sax-js/issues"
|
||||||
|
},
|
||||||
|
"readme": "ERROR: No README data found!",
|
||||||
|
"homepage": "https://github.com/isaacs/sax-js#readme"
|
||||||
|
}
|
75
node_modules/elementtree/package.json
generated
vendored
Normal file
75
node_modules/elementtree/package.json
generated
vendored
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
{
|
||||||
|
"author": {
|
||||||
|
"name": "Rackspace US, Inc."
|
||||||
|
},
|
||||||
|
"contributors": [
|
||||||
|
{
|
||||||
|
"name": "Paul Querna",
|
||||||
|
"email": "paul.querna@rackspace.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Tomaz Muraus",
|
||||||
|
"email": "tomaz.muraus@rackspace.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "elementtree",
|
||||||
|
"description": "XML Serialization and Parsing module based on Python's ElementTree.",
|
||||||
|
"version": "0.1.6",
|
||||||
|
"keywords": [
|
||||||
|
"xml",
|
||||||
|
"sax",
|
||||||
|
"parser",
|
||||||
|
"seralization",
|
||||||
|
"elementtree"
|
||||||
|
],
|
||||||
|
"homepage": "https://github.com/racker/node-elementtree",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git://github.com/racker/node-elementtree.git"
|
||||||
|
},
|
||||||
|
"main": "lib/elementtree.js",
|
||||||
|
"directories": {
|
||||||
|
"lib": "lib"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"test": "make test"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"sax": "0.3.5"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"whiskey": "0.8.x"
|
||||||
|
},
|
||||||
|
"licenses": [
|
||||||
|
{
|
||||||
|
"type": "Apache",
|
||||||
|
"url": "http://www.apache.org/licenses/LICENSE-2.0.html"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/racker/node-elementtree/issues"
|
||||||
|
},
|
||||||
|
"_id": "elementtree@0.1.6",
|
||||||
|
"dist": {
|
||||||
|
"shasum": "2ac4c46ea30516c8c4cbdb5e3ac7418e592de20c",
|
||||||
|
"tarball": "http://registry.npmjs.org/elementtree/-/elementtree-0.1.6.tgz"
|
||||||
|
},
|
||||||
|
"_from": "elementtree@>=0.1.6 <0.2.0",
|
||||||
|
"_npmVersion": "1.3.24",
|
||||||
|
"_npmUser": {
|
||||||
|
"name": "rphillips",
|
||||||
|
"email": "ryan@trolocsis.com"
|
||||||
|
},
|
||||||
|
"maintainers": [
|
||||||
|
{
|
||||||
|
"name": "rphillips",
|
||||||
|
"email": "ryan@trolocsis.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"_shasum": "2ac4c46ea30516c8c4cbdb5e3ac7418e592de20c",
|
||||||
|
"_resolved": "https://registry.npmjs.org/elementtree/-/elementtree-0.1.6.tgz",
|
||||||
|
"readme": "ERROR: No README data found!"
|
||||||
|
}
|
1
node_modules/nopt/.npmignore
generated
vendored
Normal file
1
node_modules/nopt/.npmignore
generated
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
node_modules
|
9
node_modules/nopt/.travis.yml
generated
vendored
Normal file
9
node_modules/nopt/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
language: node_js
|
||||||
|
language: node_js
|
||||||
|
node_js:
|
||||||
|
- '0.8'
|
||||||
|
- '0.10'
|
||||||
|
- '0.12'
|
||||||
|
- 'iojs'
|
||||||
|
before_install:
|
||||||
|
- npm install -g npm@latest
|
15
node_modules/nopt/LICENSE
generated
vendored
Normal file
15
node_modules/nopt/LICENSE
generated
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
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.
|
211
node_modules/nopt/README.md
generated
vendored
Normal file
211
node_modules/nopt/README.md
generated
vendored
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
If you want to write an option parser, and have it be good, there are
|
||||||
|
two ways to do it. The Right Way, and the Wrong Way.
|
||||||
|
|
||||||
|
The Wrong Way is to sit down and write an option parser. We've all done
|
||||||
|
that.
|
||||||
|
|
||||||
|
The Right Way is to write some complex configurable program with so many
|
||||||
|
options that you hit the limit of your frustration just trying to
|
||||||
|
manage them all, and defer it with duct-tape solutions until you see
|
||||||
|
exactly to the core of the problem, and finally snap and write an
|
||||||
|
awesome option parser.
|
||||||
|
|
||||||
|
If you want to write an option parser, don't write an option parser.
|
||||||
|
Write a package manager, or a source control system, or a service
|
||||||
|
restarter, or an operating system. You probably won't end up with a
|
||||||
|
good one of those, but if you don't give up, and you are relentless and
|
||||||
|
diligent enough in your procrastination, you may just end up with a very
|
||||||
|
nice option parser.
|
||||||
|
|
||||||
|
## USAGE
|
||||||
|
|
||||||
|
// my-program.js
|
||||||
|
var nopt = require("nopt")
|
||||||
|
, Stream = require("stream").Stream
|
||||||
|
, path = require("path")
|
||||||
|
, knownOpts = { "foo" : [String, null]
|
||||||
|
, "bar" : [Stream, Number]
|
||||||
|
, "baz" : path
|
||||||
|
, "bloo" : [ "big", "medium", "small" ]
|
||||||
|
, "flag" : Boolean
|
||||||
|
, "pick" : Boolean
|
||||||
|
, "many1" : [String, Array]
|
||||||
|
, "many2" : [path]
|
||||||
|
}
|
||||||
|
, shortHands = { "foofoo" : ["--foo", "Mr. Foo"]
|
||||||
|
, "b7" : ["--bar", "7"]
|
||||||
|
, "m" : ["--bloo", "medium"]
|
||||||
|
, "p" : ["--pick"]
|
||||||
|
, "f" : ["--flag"]
|
||||||
|
}
|
||||||
|
// everything is optional.
|
||||||
|
// knownOpts and shorthands default to {}
|
||||||
|
// arg list defaults to process.argv
|
||||||
|
// slice defaults to 2
|
||||||
|
, parsed = nopt(knownOpts, shortHands, process.argv, 2)
|
||||||
|
console.log(parsed)
|
||||||
|
|
||||||
|
This would give you support for any of the following:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ node my-program.js --foo "blerp" --no-flag
|
||||||
|
{ "foo" : "blerp", "flag" : false }
|
||||||
|
|
||||||
|
$ node my-program.js ---bar 7 --foo "Mr. Hand" --flag
|
||||||
|
{ bar: 7, foo: "Mr. Hand", flag: true }
|
||||||
|
|
||||||
|
$ node my-program.js --foo "blerp" -f -----p
|
||||||
|
{ foo: "blerp", flag: true, pick: true }
|
||||||
|
|
||||||
|
$ node my-program.js -fp --foofoo
|
||||||
|
{ foo: "Mr. Foo", flag: true, pick: true }
|
||||||
|
|
||||||
|
$ node my-program.js --foofoo -- -fp # -- stops the flag parsing.
|
||||||
|
{ foo: "Mr. Foo", argv: { remain: ["-fp"] } }
|
||||||
|
|
||||||
|
$ node my-program.js --blatzk -fp # unknown opts are ok.
|
||||||
|
{ blatzk: true, flag: true, pick: true }
|
||||||
|
|
||||||
|
$ node my-program.js --blatzk=1000 -fp # but you need to use = if they have a value
|
||||||
|
{ blatzk: 1000, flag: true, pick: true }
|
||||||
|
|
||||||
|
$ node my-program.js --no-blatzk -fp # unless they start with "no-"
|
||||||
|
{ blatzk: false, flag: true, pick: true }
|
||||||
|
|
||||||
|
$ node my-program.js --baz b/a/z # known paths are resolved.
|
||||||
|
{ baz: "/Users/isaacs/b/a/z" }
|
||||||
|
|
||||||
|
# if Array is one of the types, then it can take many
|
||||||
|
# values, and will always be an array. The other types provided
|
||||||
|
# specify what types are allowed in the list.
|
||||||
|
|
||||||
|
$ node my-program.js --many1 5 --many1 null --many1 foo
|
||||||
|
{ many1: ["5", "null", "foo"] }
|
||||||
|
|
||||||
|
$ node my-program.js --many2 foo --many2 bar
|
||||||
|
{ many2: ["/path/to/foo", "path/to/bar"] }
|
||||||
|
```
|
||||||
|
|
||||||
|
Read the tests at the bottom of `lib/nopt.js` for more examples of
|
||||||
|
what this puppy can do.
|
||||||
|
|
||||||
|
## Types
|
||||||
|
|
||||||
|
The following types are supported, and defined on `nopt.typeDefs`
|
||||||
|
|
||||||
|
* String: A normal string. No parsing is done.
|
||||||
|
* path: A file system path. Gets resolved against cwd if not absolute.
|
||||||
|
* url: A url. If it doesn't parse, it isn't accepted.
|
||||||
|
* Number: Must be numeric.
|
||||||
|
* Date: Must parse as a date. If it does, and `Date` is one of the options,
|
||||||
|
then it will return a Date object, not a string.
|
||||||
|
* Boolean: Must be either `true` or `false`. If an option is a boolean,
|
||||||
|
then it does not need a value, and its presence will imply `true` as
|
||||||
|
the value. To negate boolean flags, do `--no-whatever` or `--whatever
|
||||||
|
false`
|
||||||
|
* NaN: Means that the option is strictly not allowed. Any value will
|
||||||
|
fail.
|
||||||
|
* Stream: An object matching the "Stream" class in node. Valuable
|
||||||
|
for use when validating programmatically. (npm uses this to let you
|
||||||
|
supply any WriteStream on the `outfd` and `logfd` config options.)
|
||||||
|
* Array: If `Array` is specified as one of the types, then the value
|
||||||
|
will be parsed as a list of options. This means that multiple values
|
||||||
|
can be specified, and that the value will always be an array.
|
||||||
|
|
||||||
|
If a type is an array of values not on this list, then those are
|
||||||
|
considered valid values. For instance, in the example above, the
|
||||||
|
`--bloo` option can only be one of `"big"`, `"medium"`, or `"small"`,
|
||||||
|
and any other value will be rejected.
|
||||||
|
|
||||||
|
When parsing unknown fields, `"true"`, `"false"`, and `"null"` will be
|
||||||
|
interpreted as their JavaScript equivalents.
|
||||||
|
|
||||||
|
You can also mix types and values, or multiple types, in a list. For
|
||||||
|
instance `{ blah: [Number, null] }` would allow a value to be set to
|
||||||
|
either a Number or null. When types are ordered, this implies a
|
||||||
|
preference, and the first type that can be used to properly interpret
|
||||||
|
the value will be used.
|
||||||
|
|
||||||
|
To define a new type, add it to `nopt.typeDefs`. Each item in that
|
||||||
|
hash is an object with a `type` member and a `validate` method. The
|
||||||
|
`type` member is an object that matches what goes in the type list. The
|
||||||
|
`validate` method is a function that gets called with `validate(data,
|
||||||
|
key, val)`. Validate methods should assign `data[key]` to the valid
|
||||||
|
value of `val` if it can be handled properly, or return boolean
|
||||||
|
`false` if it cannot.
|
||||||
|
|
||||||
|
You can also call `nopt.clean(data, types, typeDefs)` to clean up a
|
||||||
|
config object and remove its invalid properties.
|
||||||
|
|
||||||
|
## Error Handling
|
||||||
|
|
||||||
|
By default, nopt outputs a warning to standard error when invalid values for
|
||||||
|
known options are found. You can change this behavior by assigning a method
|
||||||
|
to `nopt.invalidHandler`. This method will be called with
|
||||||
|
the offending `nopt.invalidHandler(key, val, types)`.
|
||||||
|
|
||||||
|
If no `nopt.invalidHandler` is assigned, then it will console.error
|
||||||
|
its whining. If it is assigned to boolean `false` then the warning is
|
||||||
|
suppressed.
|
||||||
|
|
||||||
|
## Abbreviations
|
||||||
|
|
||||||
|
Yes, they are supported. If you define options like this:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
{ "foolhardyelephants" : Boolean
|
||||||
|
, "pileofmonkeys" : Boolean }
|
||||||
|
```
|
||||||
|
|
||||||
|
Then this will work:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
node program.js --foolhar --pil
|
||||||
|
node program.js --no-f --pileofmon
|
||||||
|
# etc.
|
||||||
|
```
|
||||||
|
|
||||||
|
## Shorthands
|
||||||
|
|
||||||
|
Shorthands are a hash of shorter option names to a snippet of args that
|
||||||
|
they expand to.
|
||||||
|
|
||||||
|
If multiple one-character shorthands are all combined, and the
|
||||||
|
combination does not unambiguously match any other option or shorthand,
|
||||||
|
then they will be broken up into their constituent parts. For example:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "s" : ["--loglevel", "silent"]
|
||||||
|
, "g" : "--global"
|
||||||
|
, "f" : "--force"
|
||||||
|
, "p" : "--parseable"
|
||||||
|
, "l" : "--long"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm ls -sgflp
|
||||||
|
# just like doing this:
|
||||||
|
npm ls --loglevel silent --global --force --long --parseable
|
||||||
|
```
|
||||||
|
|
||||||
|
## The Rest of the args
|
||||||
|
|
||||||
|
The config object returned by nopt is given a special member called
|
||||||
|
`argv`, which is an object with the following fields:
|
||||||
|
|
||||||
|
* `remain`: The remaining args after all the parsing has occurred.
|
||||||
|
* `original`: The args as they originally appeared.
|
||||||
|
* `cooked`: The args after flags and shorthands are expanded.
|
||||||
|
|
||||||
|
## Slicing
|
||||||
|
|
||||||
|
Node programs are called with more or less the exact argv as it appears
|
||||||
|
in C land, after the v8 and node-specific options have been plucked off.
|
||||||
|
As such, `argv[0]` is always `node` and `argv[1]` is always the
|
||||||
|
JavaScript program being run.
|
||||||
|
|
||||||
|
That's usually not very useful to you. So they're sliced off by
|
||||||
|
default. If you want them, then you can pass in `0` as the last
|
||||||
|
argument, or any other number that you'd like to slice off the start of
|
||||||
|
the list.
|
54
node_modules/nopt/bin/nopt.js
generated
vendored
Normal file
54
node_modules/nopt/bin/nopt.js
generated
vendored
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
var nopt = require("../lib/nopt")
|
||||||
|
, path = require("path")
|
||||||
|
, types = { num: Number
|
||||||
|
, bool: Boolean
|
||||||
|
, help: Boolean
|
||||||
|
, list: Array
|
||||||
|
, "num-list": [Number, Array]
|
||||||
|
, "str-list": [String, Array]
|
||||||
|
, "bool-list": [Boolean, Array]
|
||||||
|
, str: String
|
||||||
|
, clear: Boolean
|
||||||
|
, config: Boolean
|
||||||
|
, length: Number
|
||||||
|
, file: path
|
||||||
|
}
|
||||||
|
, shorthands = { s: [ "--str", "astring" ]
|
||||||
|
, b: [ "--bool" ]
|
||||||
|
, nb: [ "--no-bool" ]
|
||||||
|
, tft: [ "--bool-list", "--no-bool-list", "--bool-list", "true" ]
|
||||||
|
, "?": ["--help"]
|
||||||
|
, h: ["--help"]
|
||||||
|
, H: ["--help"]
|
||||||
|
, n: [ "--num", "125" ]
|
||||||
|
, c: ["--config"]
|
||||||
|
, l: ["--length"]
|
||||||
|
, f: ["--file"]
|
||||||
|
}
|
||||||
|
, parsed = nopt( types
|
||||||
|
, shorthands
|
||||||
|
, process.argv
|
||||||
|
, 2 )
|
||||||
|
|
||||||
|
console.log("parsed", parsed)
|
||||||
|
|
||||||
|
if (parsed.help) {
|
||||||
|
console.log("")
|
||||||
|
console.log("nopt cli tester")
|
||||||
|
console.log("")
|
||||||
|
console.log("types")
|
||||||
|
console.log(Object.keys(types).map(function M (t) {
|
||||||
|
var type = types[t]
|
||||||
|
if (Array.isArray(type)) {
|
||||||
|
return [t, type.map(function (type) { return type.name })]
|
||||||
|
}
|
||||||
|
return [t, type && type.name]
|
||||||
|
}).reduce(function (s, i) {
|
||||||
|
s[i[0]] = i[1]
|
||||||
|
return s
|
||||||
|
}, {}))
|
||||||
|
console.log("")
|
||||||
|
console.log("shorthands")
|
||||||
|
console.log(shorthands)
|
||||||
|
}
|
0
bin/node_modules/nopt/lib/nopt.js → node_modules/nopt/lib/nopt.js
generated
vendored
0
bin/node_modules/nopt/lib/nopt.js → node_modules/nopt/lib/nopt.js
generated
vendored
4
node_modules/nopt/node_modules/abbrev/.npmignore
generated
vendored
Normal file
4
node_modules/nopt/node_modules/abbrev/.npmignore
generated
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
.nyc_output
|
||||||
|
nyc_output
|
||||||
|
node_modules
|
||||||
|
coverage
|
5
node_modules/nopt/node_modules/abbrev/.travis.yml
generated
vendored
Normal file
5
node_modules/nopt/node_modules/abbrev/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
language: node_js
|
||||||
|
node_js:
|
||||||
|
- '0.10'
|
||||||
|
- '0.12'
|
||||||
|
- 'iojs'
|
3
node_modules/nopt/node_modules/abbrev/CONTRIBUTING.md
generated
vendored
Normal file
3
node_modules/nopt/node_modules/abbrev/CONTRIBUTING.md
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
To get started, <a
|
||||||
|
href="http://www.clahub.com/agreements/isaacs/abbrev-js">sign the
|
||||||
|
Contributor License Agreement</a>.
|
15
node_modules/nopt/node_modules/abbrev/LICENSE
generated
vendored
Normal file
15
node_modules/nopt/node_modules/abbrev/LICENSE
generated
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
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.
|
23
node_modules/nopt/node_modules/abbrev/README.md
generated
vendored
Normal file
23
node_modules/nopt/node_modules/abbrev/README.md
generated
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
# abbrev-js
|
||||||
|
|
||||||
|
Just like [ruby's Abbrev](http://apidock.com/ruby/Abbrev).
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
|
||||||
|
var abbrev = require("abbrev");
|
||||||
|
abbrev("foo", "fool", "folding", "flop");
|
||||||
|
|
||||||
|
// returns:
|
||||||
|
{ fl: 'flop'
|
||||||
|
, flo: 'flop'
|
||||||
|
, flop: 'flop'
|
||||||
|
, fol: 'folding'
|
||||||
|
, fold: 'folding'
|
||||||
|
, foldi: 'folding'
|
||||||
|
, foldin: 'folding'
|
||||||
|
, folding: 'folding'
|
||||||
|
, foo: 'foo'
|
||||||
|
, fool: 'fool'
|
||||||
|
}
|
||||||
|
|
||||||
|
This is handy for command-line scripts, or other cases where you want to be able to accept shorthands.
|
48
node_modules/nopt/node_modules/abbrev/package.json
generated
vendored
Normal file
48
node_modules/nopt/node_modules/abbrev/package.json
generated
vendored
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
{
|
||||||
|
"name": "abbrev",
|
||||||
|
"version": "1.0.7",
|
||||||
|
"description": "Like ruby's abbrev module, but in js",
|
||||||
|
"author": {
|
||||||
|
"name": "Isaac Z. Schlueter",
|
||||||
|
"email": "i@izs.me"
|
||||||
|
},
|
||||||
|
"main": "abbrev.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "tap test.js --cov"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+ssh://git@github.com/isaacs/abbrev-js.git"
|
||||||
|
},
|
||||||
|
"license": "ISC",
|
||||||
|
"devDependencies": {
|
||||||
|
"tap": "^1.2.0"
|
||||||
|
},
|
||||||
|
"gitHead": "821d09ce7da33627f91bbd8ed631497ed6f760c2",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/isaacs/abbrev-js/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/isaacs/abbrev-js#readme",
|
||||||
|
"_id": "abbrev@1.0.7",
|
||||||
|
"_shasum": "5b6035b2ee9d4fb5cf859f08a9be81b208491843",
|
||||||
|
"_from": "abbrev@>=1.0.0 <2.0.0",
|
||||||
|
"_npmVersion": "2.10.1",
|
||||||
|
"_nodeVersion": "2.0.1",
|
||||||
|
"_npmUser": {
|
||||||
|
"name": "isaacs",
|
||||||
|
"email": "isaacs@npmjs.com"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"shasum": "5b6035b2ee9d4fb5cf859f08a9be81b208491843",
|
||||||
|
"tarball": "http://registry.npmjs.org/abbrev/-/abbrev-1.0.7.tgz"
|
||||||
|
},
|
||||||
|
"maintainers": [
|
||||||
|
{
|
||||||
|
"name": "isaacs",
|
||||||
|
"email": "i@izs.me"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"directories": {},
|
||||||
|
"_resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.7.tgz",
|
||||||
|
"readme": "ERROR: No README data found!"
|
||||||
|
}
|
47
node_modules/nopt/node_modules/abbrev/test.js
generated
vendored
Normal file
47
node_modules/nopt/node_modules/abbrev/test.js
generated
vendored
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
var abbrev = require('./abbrev.js')
|
||||||
|
var assert = require("assert")
|
||||||
|
var util = require("util")
|
||||||
|
|
||||||
|
console.log("TAP version 13")
|
||||||
|
var count = 0
|
||||||
|
|
||||||
|
function test (list, expect) {
|
||||||
|
count++
|
||||||
|
var actual = abbrev(list)
|
||||||
|
assert.deepEqual(actual, expect,
|
||||||
|
"abbrev("+util.inspect(list)+") === " + util.inspect(expect) + "\n"+
|
||||||
|
"actual: "+util.inspect(actual))
|
||||||
|
actual = abbrev.apply(exports, list)
|
||||||
|
assert.deepEqual(abbrev.apply(exports, list), expect,
|
||||||
|
"abbrev("+list.map(JSON.stringify).join(",")+") === " + util.inspect(expect) + "\n"+
|
||||||
|
"actual: "+util.inspect(actual))
|
||||||
|
console.log('ok - ' + list.join(' '))
|
||||||
|
}
|
||||||
|
|
||||||
|
test([ "ruby", "ruby", "rules", "rules", "rules" ],
|
||||||
|
{ rub: 'ruby'
|
||||||
|
, ruby: 'ruby'
|
||||||
|
, rul: 'rules'
|
||||||
|
, rule: 'rules'
|
||||||
|
, rules: 'rules'
|
||||||
|
})
|
||||||
|
test(["fool", "foom", "pool", "pope"],
|
||||||
|
{ fool: 'fool'
|
||||||
|
, foom: 'foom'
|
||||||
|
, poo: 'pool'
|
||||||
|
, pool: 'pool'
|
||||||
|
, pop: 'pope'
|
||||||
|
, pope: 'pope'
|
||||||
|
})
|
||||||
|
test(["a", "ab", "abc", "abcd", "abcde", "acde"],
|
||||||
|
{ a: 'a'
|
||||||
|
, ab: 'ab'
|
||||||
|
, abc: 'abc'
|
||||||
|
, abcd: 'abcd'
|
||||||
|
, abcde: 'abcde'
|
||||||
|
, ac: 'acde'
|
||||||
|
, acd: 'acde'
|
||||||
|
, acde: 'acde'
|
||||||
|
})
|
||||||
|
|
||||||
|
console.log("1..%d", count)
|
59
node_modules/nopt/package.json
generated
vendored
Normal file
59
node_modules/nopt/package.json
generated
vendored
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
{
|
||||||
|
"name": "nopt",
|
||||||
|
"version": "3.0.4",
|
||||||
|
"description": "Option parsing for Node, supporting types, shorthands, etc. Used by npm.",
|
||||||
|
"author": {
|
||||||
|
"name": "Isaac Z. Schlueter",
|
||||||
|
"email": "i@izs.me",
|
||||||
|
"url": "http://blog.izs.me/"
|
||||||
|
},
|
||||||
|
"main": "lib/nopt.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "tap test/*.js"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+ssh://git@github.com/isaacs/nopt.git"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"nopt": "./bin/nopt.js"
|
||||||
|
},
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"abbrev": "1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"tap": "^1.2.0"
|
||||||
|
},
|
||||||
|
"gitHead": "f52626631ea1afef5a6dd9acf23ddd1466831a08",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/isaacs/nopt/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/isaacs/nopt#readme",
|
||||||
|
"_id": "nopt@3.0.4",
|
||||||
|
"_shasum": "dd63bc9c72a6e4e85b85cdc0ca314598facede5e",
|
||||||
|
"_from": "nopt@>=3.0.1 <4.0.0",
|
||||||
|
"_npmVersion": "2.14.3",
|
||||||
|
"_nodeVersion": "2.2.2",
|
||||||
|
"_npmUser": {
|
||||||
|
"name": "zkat",
|
||||||
|
"email": "kat@sykosomatic.org"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"shasum": "dd63bc9c72a6e4e85b85cdc0ca314598facede5e",
|
||||||
|
"tarball": "http://registry.npmjs.org/nopt/-/nopt-3.0.4.tgz"
|
||||||
|
},
|
||||||
|
"maintainers": [
|
||||||
|
{
|
||||||
|
"name": "isaacs",
|
||||||
|
"email": "isaacs@npmjs.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "zkat",
|
||||||
|
"email": "kat@sykosomatic.org"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"directories": {},
|
||||||
|
"_resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.4.tgz",
|
||||||
|
"readme": "ERROR: No README data found!"
|
||||||
|
}
|
51
node_modules/properties-parser/README.markdown
generated
vendored
Normal file
51
node_modules/properties-parser/README.markdown
generated
vendored
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
# node-properties-parser
|
||||||
|
|
||||||
|
A parser for [.properties](http://en.wikipedia.org/wiki/.properties) files written in javascript. Properties files store key-value pairs. They are typically used for configuration and internationalization in Java applications as well as in Actionscript projects. Here's an example of the format:
|
||||||
|
|
||||||
|
# You are reading the ".properties" entry.
|
||||||
|
! The exclamation mark can also mark text as comments.
|
||||||
|
website = http://en.wikipedia.org/
|
||||||
|
language = English
|
||||||
|
# The backslash below tells the application to continue reading
|
||||||
|
# the value onto the next line.
|
||||||
|
message = Welcome to \
|
||||||
|
Wikipedia!
|
||||||
|
# Add spaces to the key
|
||||||
|
key\ with\ spaces = This is the value that could be looked up with the key "key with spaces".
|
||||||
|
# Unicode
|
||||||
|
tab : \u0009
|
||||||
|
*(taken from [Wikipedia](http://en.wikipedia.org/wiki/.properties#Format))*
|
||||||
|
|
||||||
|
Currently works with any version of node.js.
|
||||||
|
|
||||||
|
## The API
|
||||||
|
|
||||||
|
- `parse(text)`: Parses `text` into key-value pairs. Returns an object containing the key-value pairs.
|
||||||
|
- `read(path[, callback])`: Opens the file specified by `path` and calls `parse` on its content. If the optional `callback` parameter is provided, the result is then passed to it as the second parameter. If an error occurs, the error object is passed to `callback` as the first parameter. If `callback` is not provided, the file specified by `path` is synchronously read and calls `parse` on its contents. The resulting object is immediately returned.
|
||||||
|
- `createEditor([path][, options][, callback]])`: If neither `path` or `callback` are provided an empty editor object is returned synchronously. If only `path` is provided, the file specified by `path` is synchronously read and parsed. An editor object with the results in then immediately returned. If both `path` and `callback` are provided, the file specified by `path` is read and parsed asynchronously. An editor object with the results are then passed to `callback` as the second parameters. If an error occurs, the error object is passed to `callback` as the first parameter. The following options are supported:
|
||||||
|
- `options.separator`: The character used to separate key/values. Defaults to "=".
|
||||||
|
- `options.path`: Treated the same way as the optional `path` argument. If both are provided the arguement wins.
|
||||||
|
- `options.callback`: Treated the same way as the optional `callback` parameter. If both are provided the arguement wins.
|
||||||
|
- `Editor`: The editor object is returned by `createEditor`. Has the following API:
|
||||||
|
- `get(key)`: Returns the value currently associated with `key`.
|
||||||
|
- `set(key, [value[, comment]])`: Associates `key` with `value`. An optional comment can be provided. If `value` is not specified or is `null`, then `key` is unset.
|
||||||
|
- `unset(key)`: Unsets the specified `key`.
|
||||||
|
- `save([path][, callback]])`: Writes the current contents of this editor object to a file specified by `path`. If `path` is not provided, then it'll be defaulted to the `path` value passed to `createEditor`. The `callback` parameter is called when the file has been written to disk.
|
||||||
|
- `addHeadComment`: Added a comment to the head of the file.
|
||||||
|
- `toString`: Returns the string representation of this properties editor object. This string will be written to a file if `save` is called.
|
||||||
|
|
||||||
|
## Getting node-properties-parser
|
||||||
|
|
||||||
|
The easiest way to get node-properties-parser is with [npm](http://npmjs.org/):
|
||||||
|
|
||||||
|
npm install properties-parser
|
||||||
|
|
||||||
|
Alternatively you can clone this git repository:
|
||||||
|
|
||||||
|
git://github.com/xavi-/node-properties-parser.git
|
||||||
|
|
||||||
|
## Developed by
|
||||||
|
* Xavi Ramirez
|
||||||
|
|
||||||
|
## License
|
||||||
|
This project is released under [The MIT License](http://www.opensource.org/licenses/mit-license.php).
|
420
node_modules/properties-parser/index.js
generated
vendored
Normal file
420
node_modules/properties-parser/index.js
generated
vendored
Normal file
@ -0,0 +1,420 @@
|
|||||||
|
var fs = require("fs");
|
||||||
|
|
||||||
|
function Iterator(text) {
|
||||||
|
var pos = 0, length = text.length;
|
||||||
|
|
||||||
|
this.peek = function(num) {
|
||||||
|
num = num || 0;
|
||||||
|
if(pos + num >= length) { return null; }
|
||||||
|
|
||||||
|
return text.charAt(pos + num);
|
||||||
|
};
|
||||||
|
this.next = function(inc) {
|
||||||
|
inc = inc || 1;
|
||||||
|
|
||||||
|
if(pos >= length) { return null; }
|
||||||
|
|
||||||
|
return text.charAt((pos += inc) - inc);
|
||||||
|
};
|
||||||
|
this.pos = function() {
|
||||||
|
return pos;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var rWhitespace = /\s/;
|
||||||
|
function isWhitespace(chr) {
|
||||||
|
return rWhitespace.test(chr);
|
||||||
|
}
|
||||||
|
function consumeWhiteSpace(iter) {
|
||||||
|
var start = iter.pos();
|
||||||
|
|
||||||
|
while(isWhitespace(iter.peek())) { iter.next(); }
|
||||||
|
|
||||||
|
return { type: "whitespace", start: start, end: iter.pos() };
|
||||||
|
}
|
||||||
|
|
||||||
|
function startsComment(chr) {
|
||||||
|
return chr === "!" || chr === "#";
|
||||||
|
}
|
||||||
|
function isEOL(chr) {
|
||||||
|
return chr == null || chr === "\n" || chr === "\r";
|
||||||
|
}
|
||||||
|
function consumeComment(iter) {
|
||||||
|
var start = iter.pos();
|
||||||
|
|
||||||
|
while(!isEOL(iter.peek())) { iter.next(); }
|
||||||
|
|
||||||
|
return { type: "comment", start: start, end: iter.pos() };
|
||||||
|
}
|
||||||
|
|
||||||
|
function startsKeyVal(chr) {
|
||||||
|
return !isWhitespace(chr) && !startsComment(chr);
|
||||||
|
}
|
||||||
|
function startsSeparator(chr) {
|
||||||
|
return chr === "=" || chr === ":" || isWhitespace(chr);
|
||||||
|
}
|
||||||
|
function startsEscapedVal(chr) {
|
||||||
|
return chr === "\\";
|
||||||
|
}
|
||||||
|
function consumeEscapedVal(iter) {
|
||||||
|
var start = iter.pos();
|
||||||
|
|
||||||
|
iter.next(); // move past "\"
|
||||||
|
var curChar = iter.next();
|
||||||
|
if(curChar === "u") { // encoded unicode char
|
||||||
|
iter.next(4); // Read in the 4 hex values
|
||||||
|
}
|
||||||
|
|
||||||
|
return { type: "escaped-value", start: start, end: iter.pos() };
|
||||||
|
}
|
||||||
|
function consumeKey(iter) {
|
||||||
|
var start = iter.pos(), children = [];
|
||||||
|
|
||||||
|
var curChar;
|
||||||
|
while((curChar = iter.peek()) !== null) {
|
||||||
|
if(startsSeparator(curChar)) { break; }
|
||||||
|
if(startsEscapedVal(curChar)) { children.push(consumeEscapedVal(iter)); continue; }
|
||||||
|
|
||||||
|
iter.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
return { type: "key", start: start, end: iter.pos(), children: children };
|
||||||
|
}
|
||||||
|
function consumeKeyValSeparator(iter) {
|
||||||
|
var start = iter.pos();
|
||||||
|
|
||||||
|
var seenHardSep = false, curChar;
|
||||||
|
while((curChar = iter.peek()) !== null) {
|
||||||
|
if(isEOL(curChar)) { break; }
|
||||||
|
|
||||||
|
if(isWhitespace(curChar)) { iter.next(); continue; }
|
||||||
|
|
||||||
|
if(seenHardSep) { break; }
|
||||||
|
|
||||||
|
seenHardSep = (curChar === ":" || curChar === "=");
|
||||||
|
if(seenHardSep) { iter.next(); continue; }
|
||||||
|
|
||||||
|
break; // curChar is a non-separtor char
|
||||||
|
}
|
||||||
|
|
||||||
|
return { type: "key-value-separator", start: start, end: iter.pos() };
|
||||||
|
}
|
||||||
|
function startsLineBreak(iter) {
|
||||||
|
return iter.peek() === "\\" && isEOL(iter.peek(1));
|
||||||
|
}
|
||||||
|
function consumeLineBreak(iter) {
|
||||||
|
var start = iter.pos();
|
||||||
|
|
||||||
|
iter.next(); // consume \
|
||||||
|
if(iter.peek() === "\r") { iter.next(); }
|
||||||
|
iter.next(); // consume \n
|
||||||
|
|
||||||
|
var curChar;
|
||||||
|
while((curChar = iter.peek()) !== null) {
|
||||||
|
if(isEOL(curChar)) { break; }
|
||||||
|
if(!isWhitespace(curChar)) { break; }
|
||||||
|
|
||||||
|
iter.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
return { type: "line-break", start: start, end: iter.pos() };
|
||||||
|
}
|
||||||
|
function consumeVal(iter) {
|
||||||
|
var start = iter.pos(), children = [];
|
||||||
|
|
||||||
|
var curChar;
|
||||||
|
while((curChar = iter.peek()) !== null) {
|
||||||
|
if(startsLineBreak(iter)) { children.push(consumeLineBreak(iter)); continue; }
|
||||||
|
if(startsEscapedVal(curChar)) { children.push(consumeEscapedVal(iter)); continue; }
|
||||||
|
if(isEOL(curChar)) { break; }
|
||||||
|
|
||||||
|
iter.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
return { type: "value", start: start, end: iter.pos(), children: children };
|
||||||
|
}
|
||||||
|
function consumeKeyVal(iter) {
|
||||||
|
return {
|
||||||
|
type: "key-value",
|
||||||
|
start: iter.pos(),
|
||||||
|
children: [
|
||||||
|
consumeKey(iter),
|
||||||
|
consumeKeyValSeparator(iter),
|
||||||
|
consumeVal(iter)
|
||||||
|
],
|
||||||
|
end: iter.pos()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var renderChild = {
|
||||||
|
"escaped-value": function(child, text) {
|
||||||
|
var type = text.charAt(child.start + 1);
|
||||||
|
|
||||||
|
if(type === "t") { return "\t"; }
|
||||||
|
if(type === "r") { return "\r"; }
|
||||||
|
if(type === "n") { return "\n"; }
|
||||||
|
if(type === "f") { return "\f"; }
|
||||||
|
if(type !== "u") { return type; }
|
||||||
|
|
||||||
|
return String.fromCharCode(parseInt(text.substr(child.start + 2, 4), 16));
|
||||||
|
},
|
||||||
|
"line-break": function (child, text) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
function rangeToBuffer(range, text) {
|
||||||
|
var start = range.start, buffer = [];
|
||||||
|
|
||||||
|
for(var i = 0; i < range.children.length; i++) {
|
||||||
|
var child = range.children[i];
|
||||||
|
|
||||||
|
buffer.push(text.substring(start, child.start));
|
||||||
|
buffer.push(renderChild[child.type](child, text));
|
||||||
|
start = child.end;
|
||||||
|
}
|
||||||
|
buffer.push(text.substring(start, range.end));
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
function rangesToObject(ranges, text) {
|
||||||
|
var obj = Object.create(null); // Creates to a true hash map
|
||||||
|
|
||||||
|
for(var i = 0; i < ranges.length; i++) {
|
||||||
|
var range = ranges[i];
|
||||||
|
|
||||||
|
if(range.type !== "key-value") { continue; }
|
||||||
|
|
||||||
|
var key = rangeToBuffer(range.children[0], text).join("");
|
||||||
|
var val = rangeToBuffer(range.children[2], text).join("");
|
||||||
|
obj[key] = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
function stringToRanges(text) {
|
||||||
|
var iter = new Iterator(text), ranges = [];
|
||||||
|
|
||||||
|
var curChar;
|
||||||
|
while((curChar = iter.peek()) !== null) {
|
||||||
|
if(isWhitespace(curChar)) { ranges.push(consumeWhiteSpace(iter)); continue; }
|
||||||
|
if(startsComment(curChar)) { ranges.push(consumeComment(iter)); continue; }
|
||||||
|
if(startsKeyVal(curChar)) { ranges.push(consumeKeyVal(iter)); continue; }
|
||||||
|
|
||||||
|
throw Error("Something crazy happened. text: '" + text + "'; curChar: '" + curChar + "'");
|
||||||
|
}
|
||||||
|
|
||||||
|
return ranges;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isNewLineRange(range) {
|
||||||
|
if(!range) { return false; }
|
||||||
|
|
||||||
|
if(range.type === "whitespace") { return true; }
|
||||||
|
|
||||||
|
if(range.type === "literal") {
|
||||||
|
return isWhitespace(range.text) && range.text.indexOf("\n") > -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function escapeMaker(escapes) {
|
||||||
|
return function escapeKey(key) {
|
||||||
|
var zeros = [ "", "0", "00", "000" ];
|
||||||
|
var buf = [];
|
||||||
|
|
||||||
|
for(var i = 0; i < key.length; i++) {
|
||||||
|
var chr = key.charAt(i);
|
||||||
|
|
||||||
|
if(escapes[chr]) { buf.push(escapes[chr]); continue; }
|
||||||
|
|
||||||
|
var code = chr.codePointAt(0);
|
||||||
|
|
||||||
|
if(code <= 0x7F) { buf.push(chr); continue; }
|
||||||
|
|
||||||
|
var hex = code.toString(16);
|
||||||
|
|
||||||
|
buf.push("\\u");
|
||||||
|
buf.push(zeros[4 - hex.length]);
|
||||||
|
buf.push(hex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf.join("");
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var escapeKey = escapeMaker({ " ": "\\ ", "\n": "\\n", ":": "\\:", "=": "\\=" });
|
||||||
|
var escapeVal = escapeMaker({ "\n": "\\n" });
|
||||||
|
|
||||||
|
function Editor(text, options) {
|
||||||
|
if (typeof text === 'object') {
|
||||||
|
options = text;
|
||||||
|
text = null;
|
||||||
|
}
|
||||||
|
text = text || "";
|
||||||
|
var path = options.path;
|
||||||
|
var separator = options.separator || '=';
|
||||||
|
|
||||||
|
var ranges = stringToRanges(text);
|
||||||
|
var obj = rangesToObject(ranges, text);
|
||||||
|
var keyRange = Object.create(null); // Creates to a true hash map
|
||||||
|
|
||||||
|
for(var i = 0; i < ranges.length; i++) {
|
||||||
|
var range = ranges[i];
|
||||||
|
|
||||||
|
if(range.type !== "key-value") { continue; }
|
||||||
|
|
||||||
|
var key = rangeToBuffer(range.children[0], text).join("");
|
||||||
|
keyRange[key] = range;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.addHeadComment = function(comment) {
|
||||||
|
if(comment == null) { return; }
|
||||||
|
|
||||||
|
ranges.unshift({ type: "literal", text: "# " + comment.replace(/\n/g, "\n# ") + "\n" });
|
||||||
|
};
|
||||||
|
|
||||||
|
this.get = function(key) { return obj[key]; };
|
||||||
|
this.set = function(key, val, comment) {
|
||||||
|
if(val == null) { this.unset(key); return; }
|
||||||
|
|
||||||
|
obj[key] = val;
|
||||||
|
var escapedKey = escapeKey(key);
|
||||||
|
var escapedVal = escapeVal(val);
|
||||||
|
|
||||||
|
var range = keyRange[key];
|
||||||
|
if(!range) {
|
||||||
|
keyRange[key] = range = {
|
||||||
|
type: "literal",
|
||||||
|
text: escapedKey + separator + escapedVal
|
||||||
|
};
|
||||||
|
|
||||||
|
var prevRange = ranges[ranges.length - 1];
|
||||||
|
if(prevRange != null && !isNewLineRange(prevRange)) {
|
||||||
|
ranges.push({ type: "literal", text: "\n" });
|
||||||
|
}
|
||||||
|
ranges.push(range);
|
||||||
|
}
|
||||||
|
|
||||||
|
// comment === null deletes comment. if comment === undefined, it's left alone
|
||||||
|
if(comment !== undefined) {
|
||||||
|
range.comment = comment && "# " + comment.replace(/\n/g, "\n# ") + "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if(range.type === "literal") {
|
||||||
|
range.text = escapedKey + separator + escapedVal;
|
||||||
|
if(range.comment != null) { range.text = range.comment + range.text; }
|
||||||
|
} else if(range.type === "key-value") {
|
||||||
|
range.children[2] = { type: "literal", text: escapedVal };
|
||||||
|
} else {
|
||||||
|
throw "Unknown node type: " + range.type;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.unset = function(key) {
|
||||||
|
if(!(key in obj)) { return; }
|
||||||
|
|
||||||
|
var range = keyRange[key];
|
||||||
|
var idx = ranges.indexOf(range);
|
||||||
|
|
||||||
|
ranges.splice(idx, (isNewLineRange(ranges[idx + 1]) ? 2 : 1));
|
||||||
|
|
||||||
|
delete keyRange[key];
|
||||||
|
delete obj[key];
|
||||||
|
};
|
||||||
|
this.valueOf = this.toString = function() {
|
||||||
|
var buffer = [], stack = [].concat(ranges);
|
||||||
|
|
||||||
|
var node;
|
||||||
|
while((node = stack.shift()) != null) {
|
||||||
|
switch(node.type) {
|
||||||
|
case "literal":
|
||||||
|
buffer.push(node.text);
|
||||||
|
break;
|
||||||
|
case "key":
|
||||||
|
case "value":
|
||||||
|
case "comment":
|
||||||
|
case "whitespace":
|
||||||
|
case "key-value-separator":
|
||||||
|
case "escaped-value":
|
||||||
|
case "line-break":
|
||||||
|
buffer.push(text.substring(node.start, node.end));
|
||||||
|
break;
|
||||||
|
case "key-value":
|
||||||
|
Array.prototype.unshift.apply(stack, node.children);
|
||||||
|
if(node.comment) { stack.unshift({ type: "literal", text: node.comment }); }
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer.join("");
|
||||||
|
};
|
||||||
|
this.save = function(newPath, callback) {
|
||||||
|
if(typeof newPath === 'function') {
|
||||||
|
callback = newPath;
|
||||||
|
newPath = path;
|
||||||
|
}
|
||||||
|
newPath = newPath || path;
|
||||||
|
|
||||||
|
if(!newPath) {
|
||||||
|
if (callback) {
|
||||||
|
return callback("Unknown path");
|
||||||
|
}
|
||||||
|
throw new Error("Unknown path");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (callback) {
|
||||||
|
fs.writeFile(newPath, this.toString(), callback);
|
||||||
|
} else {
|
||||||
|
fs.writeFileSync(newPath, this.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function createEditor(/*path, options, callback*/) {
|
||||||
|
var path, options, callback;
|
||||||
|
var args = Array.prototype.slice.call(arguments);
|
||||||
|
for (var i = 0; i < args.length; i ++) {
|
||||||
|
var arg = args[i];
|
||||||
|
if (!path && typeof arg === 'string') {
|
||||||
|
path = arg;
|
||||||
|
} else if (!options && typeof arg === 'object') {
|
||||||
|
options = arg;
|
||||||
|
} else if (!callback && typeof arg === 'function') {
|
||||||
|
callback = arg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
options = options || {};
|
||||||
|
path = path || options.path;
|
||||||
|
callback = callback || options.callback;
|
||||||
|
options.path = path;
|
||||||
|
|
||||||
|
if(!path) { return new Editor(options); }
|
||||||
|
|
||||||
|
if(!callback) { return new Editor(fs.readFileSync(path).toString(), options); }
|
||||||
|
|
||||||
|
return fs.readFile(path, function(err, text) {
|
||||||
|
if(err) { return callback(err, null); }
|
||||||
|
|
||||||
|
text = text.toString();
|
||||||
|
return callback(null, new Editor(text, options));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function parse(text) {
|
||||||
|
text = text.toString();
|
||||||
|
var ranges = stringToRanges(text);
|
||||||
|
return rangesToObject(ranges, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
function read(path, callback) {
|
||||||
|
if(!callback) { return parse(fs.readFileSync(path)); }
|
||||||
|
|
||||||
|
return fs.readFile(path, function(err, data) {
|
||||||
|
if(err) { return callback(err, null); }
|
||||||
|
|
||||||
|
return callback(null, parse(data));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { parse: parse, read: read, createEditor: createEditor };
|
50
node_modules/properties-parser/package.json
generated
vendored
Normal file
50
node_modules/properties-parser/package.json
generated
vendored
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
{
|
||||||
|
"name": "properties-parser",
|
||||||
|
"version": "0.3.0",
|
||||||
|
"description": "A parser for .properties files written in javascript",
|
||||||
|
"keywords": [
|
||||||
|
"parser",
|
||||||
|
".properties",
|
||||||
|
"properties",
|
||||||
|
"java",
|
||||||
|
"file parser",
|
||||||
|
"actionscript"
|
||||||
|
],
|
||||||
|
"maintainers": [
|
||||||
|
{
|
||||||
|
"name": "xavi",
|
||||||
|
"email": "xavi.rmz@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"main": "./index.js",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/xavi-/node-properties-parser.git"
|
||||||
|
},
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.3.1"
|
||||||
|
},
|
||||||
|
"gitHead": "d9f75e462c3da0e6eb33261e578e040994ff50c9",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/xavi-/node-properties-parser/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/xavi-/node-properties-parser",
|
||||||
|
"_id": "properties-parser@0.3.0",
|
||||||
|
"scripts": {},
|
||||||
|
"_shasum": "6ba6dc6ac40cf53b1ee2c2045f86623e70213caa",
|
||||||
|
"_from": "properties-parser@>=0.3.0 <0.4.0",
|
||||||
|
"_npmVersion": "2.5.1",
|
||||||
|
"_nodeVersion": "1.2.0",
|
||||||
|
"_npmUser": {
|
||||||
|
"name": "xavi",
|
||||||
|
"email": "xavi.rmz@gmail.com"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"shasum": "6ba6dc6ac40cf53b1ee2c2045f86623e70213caa",
|
||||||
|
"tarball": "http://registry.npmjs.org/properties-parser/-/properties-parser-0.3.0.tgz"
|
||||||
|
},
|
||||||
|
"directories": {},
|
||||||
|
"_resolved": "https://registry.npmjs.org/properties-parser/-/properties-parser-0.3.0.tgz",
|
||||||
|
"readme": "ERROR: No README data found!"
|
||||||
|
}
|
786
node_modules/q/CHANGES.md
generated
vendored
Normal file
786
node_modules/q/CHANGES.md
generated
vendored
Normal file
@ -0,0 +1,786 @@
|
|||||||
|
|
||||||
|
## 1.4.1
|
||||||
|
|
||||||
|
- Address an issue that prevented Q from being used as a `<script>` for
|
||||||
|
Firefox add-ons. Q can now be used in any environment that provides `window`
|
||||||
|
or `self` globals, favoring `window` since add-ons have an an immutable
|
||||||
|
`self` that is distinct from `window`.
|
||||||
|
|
||||||
|
## 1.4.0
|
||||||
|
|
||||||
|
- Add `noConflict` support for use in `<script>` (@jahnjw).
|
||||||
|
|
||||||
|
## 1.3.0
|
||||||
|
|
||||||
|
- Add tracking for unhandled and handled rejections in Node.js (@benjamingr).
|
||||||
|
|
||||||
|
## 1.2.1
|
||||||
|
|
||||||
|
- Fix Node.js environment detection for modern Browserify (@kahnjw).
|
||||||
|
|
||||||
|
## 1.2.0
|
||||||
|
|
||||||
|
- Added Q.any(promisesArray) method (@vergara).
|
||||||
|
Returns a promise fulfilled with the value of the first resolved promise in
|
||||||
|
promisesArray. If all promises in promisesArray are rejected, it returns
|
||||||
|
a rejected promise.
|
||||||
|
|
||||||
|
## 1.1.2
|
||||||
|
|
||||||
|
- Removed extraneous files from the npm package by using the "files"
|
||||||
|
whitelist in package.json instead of the .npmignore blacklist.
|
||||||
|
(@anton-rudeshko)
|
||||||
|
|
||||||
|
## 1.1.1
|
||||||
|
|
||||||
|
- Fix a pair of regressions in bootstrapping, one which precluded
|
||||||
|
WebWorker support, and another that precluded support in
|
||||||
|
``<script>`` usage outright. #607
|
||||||
|
|
||||||
|
## 1.1.0
|
||||||
|
|
||||||
|
- Adds support for enabling long stack traces in node.js by setting
|
||||||
|
environment variable `Q_DEBUG=1`.
|
||||||
|
- Introduces the `tap` method to promises, which will see a value
|
||||||
|
pass through without alteration.
|
||||||
|
- Use instanceof to recognize own promise instances as opposed to
|
||||||
|
thenables.
|
||||||
|
- Construct timeout errors with `code === ETIMEDOUT` (Kornel Lesiński)
|
||||||
|
- More descriminant CommonJS module environment detection.
|
||||||
|
- Dropped continuous integration for Node.js 0.6 and 0.8 because of
|
||||||
|
changes to npm that preclude the use of new `^` version predicate
|
||||||
|
operator in any transitive dependency.
|
||||||
|
- Users can now override `Q.nextTick`.
|
||||||
|
|
||||||
|
## 1.0.1
|
||||||
|
|
||||||
|
- Adds support for `Q.Promise`, which implements common usage of the
|
||||||
|
ES6 `Promise` constructor and its methods. `Promise` does not have
|
||||||
|
a valid promise constructor and a proper implementation awaits
|
||||||
|
version 2 of Q.
|
||||||
|
- Removes the console stopgap for a promise inspector. This no longer
|
||||||
|
works with any degree of reliability.
|
||||||
|
- Fixes support for content security policies that forbid eval. Now
|
||||||
|
using the `StopIteration` global to distinguish SpiderMonkey
|
||||||
|
generators from ES6 generators, assuming that they will never
|
||||||
|
coexist.
|
||||||
|
|
||||||
|
## 1.0.0
|
||||||
|
|
||||||
|
:cake: This is all but a re-release of version 0.9, which has settled
|
||||||
|
into a gentle maintenance mode and rightly deserves an official 1.0.
|
||||||
|
An ambitious 2.0 release is already around the corner, but 0.9/1.0
|
||||||
|
have been distributed far and wide and demand long term support.
|
||||||
|
|
||||||
|
- Q will now attempt to post a debug message in browsers regardless
|
||||||
|
of whether window.Touch is defined. Chrome at least now has this
|
||||||
|
property regardless of whether touch is supported by the underlying
|
||||||
|
hardware.
|
||||||
|
- Remove deprecation warning from `promise.valueOf`. The function is
|
||||||
|
called by the browser in various ways so there is no way to
|
||||||
|
distinguish usage that should be migrated from usage that cannot be
|
||||||
|
altered.
|
||||||
|
|
||||||
|
## 0.9.7
|
||||||
|
|
||||||
|
- :warning: `q.min.js` is no longer checked-in. It is however still
|
||||||
|
created by Grunt and NPM.
|
||||||
|
- Fixes a bug that inhibited `Q.async` with implementations of the new
|
||||||
|
ES6 generators.
|
||||||
|
- Fixes a bug with `nextTick` affecting Safari 6.0.5 the first time a
|
||||||
|
page loads when an `iframe` is involved.
|
||||||
|
- Introduces `passByCopy`, `join`, and `race`.
|
||||||
|
- Shows stack traces or error messages on the console, instead of
|
||||||
|
`Error` objects.
|
||||||
|
- Elimintates wrapper methods for improved performance.
|
||||||
|
- `Q.all` now propagates progress notifications of the form you might
|
||||||
|
expect of ES6 iterations, `{value, index}` where the `value` is the
|
||||||
|
progress notification from the promise at `index`.
|
||||||
|
|
||||||
|
## 0.9.6
|
||||||
|
|
||||||
|
- Fixes a bug in recognizing the difference between compatible Q
|
||||||
|
promises, and Q promises from before the implementation of "inspect".
|
||||||
|
The latter are now coerced.
|
||||||
|
- Fixes an infinite asynchronous coercion cycle introduced by former
|
||||||
|
solution, in two independently sufficient ways. 1.) All promises
|
||||||
|
returned by makePromise now implement "inspect", albeit a default
|
||||||
|
that reports that the promise has an "unknown" state. 2.) The
|
||||||
|
implementation of "then/when" is now in "then" instead of "when", so
|
||||||
|
that the responsibility to "coerce" the given promise rests solely in
|
||||||
|
the "when" method and the "then" method may assume that "this" is a
|
||||||
|
promise of the right type.
|
||||||
|
- Refactors `nextTick` to use an unrolled microtask within Q regardless
|
||||||
|
of how new ticks a requested. #316 @rkatic
|
||||||
|
|
||||||
|
## 0.9.5
|
||||||
|
|
||||||
|
- Introduces `inspect` for getting the state of a promise as
|
||||||
|
`{state: "fulfilled" | "rejected" | "pending", value | reason}`.
|
||||||
|
- Introduces `allSettled` which produces an array of promises states
|
||||||
|
for the input promises once they have all "settled". This is in
|
||||||
|
accordance with a discussion on Promises/A+ that "settled" refers to
|
||||||
|
a promise that is "fulfilled" or "rejected". "resolved" refers to a
|
||||||
|
deferred promise that has been "resolved" to another promise,
|
||||||
|
"sealing its fate" to the fate of the successor promise.
|
||||||
|
- Long stack traces are now off by default. Set `Q.longStackSupport`
|
||||||
|
to true to enable long stack traces.
|
||||||
|
- Long stack traces can now follow the entire asynchronous history of a
|
||||||
|
promise, not just a single jump.
|
||||||
|
- Introduces `spawn` for an immediately invoked asychronous generator.
|
||||||
|
@jlongster
|
||||||
|
- Support for *experimental* synonyms `mapply`, `mcall`, `nmapply`,
|
||||||
|
`nmcall` for method invocation.
|
||||||
|
|
||||||
|
## 0.9.4
|
||||||
|
|
||||||
|
- `isPromise` and `isPromiseAlike` now always returns a boolean
|
||||||
|
(even for falsy values). #284 @lfac-pt
|
||||||
|
- Support for ES6 Generators in `async` #288 @andywingo
|
||||||
|
- Clear duplicate promise rejections from dispatch methods #238 @SLaks
|
||||||
|
- Unhandled rejection API #296 @domenic
|
||||||
|
`stopUnhandledRejectionTracking`, `getUnhandledReasons`,
|
||||||
|
`resetUnhandledRejections`.
|
||||||
|
|
||||||
|
## 0.9.3
|
||||||
|
|
||||||
|
- Add the ability to give `Q.timeout`'s errors a custom error message. #270
|
||||||
|
@jgrenon
|
||||||
|
- Fix Q's call-stack busting behavior in Node.js 0.10, by switching from
|
||||||
|
`process.nextTick` to `setImmediate`. #254 #259
|
||||||
|
- Fix Q's behavior when used with the Mocha test runner in the browser, since
|
||||||
|
Mocha introduces a fake `process` global without a `nextTick` property. #267
|
||||||
|
- Fix some, but not all, cases wherein Q would give false positives in its
|
||||||
|
unhandled rejection detection (#252). A fix for other cases (#238) is
|
||||||
|
hopefully coming soon.
|
||||||
|
- Made `Q.promise` throw early if given a non-function.
|
||||||
|
|
||||||
|
## 0.9.2
|
||||||
|
|
||||||
|
- Pass through progress notifications when using `timeout`. #229 @omares
|
||||||
|
- Pass through progress notifications when using `delay`.
|
||||||
|
- Fix `nbind` to actually bind the `thisArg`. #232 @davidpadbury
|
||||||
|
|
||||||
|
## 0.9.1
|
||||||
|
|
||||||
|
- Made the AMD detection compatible with the RequireJS optimizer's `namespace`
|
||||||
|
option. #225 @terinjokes
|
||||||
|
- Fix side effects from `valueOf`, and thus from `isFulfilled`, `isRejected`,
|
||||||
|
and `isPending`. #226 @benjamn
|
||||||
|
|
||||||
|
## 0.9.0
|
||||||
|
|
||||||
|
This release removes many layers of deprecated methods and brings Q closer to
|
||||||
|
alignment with Mark Miller’s TC39 [strawman][] for concurrency. At the same
|
||||||
|
time, it fixes many bugs and adds a few features around error handling. Finally,
|
||||||
|
it comes with an updated and comprehensive [API Reference][].
|
||||||
|
|
||||||
|
[strawman]: http://wiki.ecmascript.org/doku.php?id=strawman:concurrency
|
||||||
|
[API Reference]: https://github.com/kriskowal/q/wiki/API-Reference
|
||||||
|
|
||||||
|
### API Cleanup
|
||||||
|
|
||||||
|
The following deprecated or undocumented methods have been removed.
|
||||||
|
Their replacements are listed here:
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>0.8.x method</th>
|
||||||
|
<th>0.9 replacement</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td><code>Q.ref</code></td>
|
||||||
|
<td><code>Q</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>call</code>, <code>apply</code>, <code>bind</code> (*)</td>
|
||||||
|
<td><code>fcall</code>/<code>invoke</code>, <code>fapply</code>/<code>post</code>, <code>fbind</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>ncall</code>, <code>napply</code> (*)</td>
|
||||||
|
<td><code>nfcall</code>/<code>ninvoke</code>, <code>nfapply</code>/<code>npost</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>end</code></td>
|
||||||
|
<td><code>done</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>put</code></td>
|
||||||
|
<td><code>set</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>node</code></td>
|
||||||
|
<td><code>nbind</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>nend</code></td>
|
||||||
|
<td><code>nodeify</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>isResolved</code></td>
|
||||||
|
<td><code>isPending</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>deferred.node</code></td>
|
||||||
|
<td><code>deferred.makeNodeResolver</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>Method</code>, <code>sender</code></td>
|
||||||
|
<td><code>dispatcher</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>send</code></td>
|
||||||
|
<td><code>dispatch</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>view</code>, <code>viewInfo</code></td>
|
||||||
|
<td>(none)</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
|
||||||
|
(*) Use of ``thisp`` is discouraged. For calling methods, use ``post`` or
|
||||||
|
``invoke``.
|
||||||
|
|
||||||
|
### Alignment with the Concurrency Strawman
|
||||||
|
|
||||||
|
- Q now exports a `Q(value)` function, an alias for `resolve`.
|
||||||
|
`Q.call`, `Q.apply`, and `Q.bind` were removed to make room for the
|
||||||
|
same methods on the function prototype.
|
||||||
|
- `invoke` has been aliased to `send` in all its forms.
|
||||||
|
- `post` with no method name acts like `fapply`.
|
||||||
|
|
||||||
|
### Error Handling
|
||||||
|
|
||||||
|
- Long stack traces can be turned off by setting `Q.stackJumpLimit` to zero.
|
||||||
|
In the future, this property will be used to fine tune how many stack jumps
|
||||||
|
are retained in long stack traces; for now, anything nonzero is treated as
|
||||||
|
one (since Q only tracks one stack jump at the moment, see #144). #168
|
||||||
|
- In Node.js, if there are unhandled rejections when the process exits, they
|
||||||
|
are output to the console. #115
|
||||||
|
|
||||||
|
### Other
|
||||||
|
|
||||||
|
- `delete` and `set` (née `put`) no longer have a fulfillment value.
|
||||||
|
- Q promises are no longer frozen, which
|
||||||
|
[helps with performance](http://code.google.com/p/v8/issues/detail?id=1858).
|
||||||
|
- `thenReject` is now included, as a counterpart to `thenResolve`.
|
||||||
|
- The included browser `nextTick` shim is now faster. #195 @rkatic.
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- Q now works in Internet Explorer 10. #186 @ForbesLindesay
|
||||||
|
- `fbind` no longer hard-binds the returned function's `this` to `undefined`.
|
||||||
|
#202
|
||||||
|
- `Q.reject` no longer leaks memory. #148
|
||||||
|
- `npost` with no arguments now works. #207
|
||||||
|
- `allResolved` now works with non-Q promises ("thenables"). #179
|
||||||
|
- `keys` behavior is now correct even in browsers without native
|
||||||
|
`Object.keys`. #192 @rkatic
|
||||||
|
- `isRejected` and the `exception` property now work correctly if the
|
||||||
|
rejection reason is falsy. #198
|
||||||
|
|
||||||
|
### Internals and Advanced
|
||||||
|
|
||||||
|
- The internal interface for a promise now uses
|
||||||
|
`dispatchPromise(resolve, op, operands)` instead of `sendPromise(op,
|
||||||
|
resolve, ...operands)`, which reduces the cases where Q needs to do
|
||||||
|
argument slicing.
|
||||||
|
- The internal protocol uses different operands. "put" is now "set".
|
||||||
|
"del" is now "delete". "view" and "viewInfo" have been removed.
|
||||||
|
- `Q.fulfill` has been added. It is distinct from `Q.resolve` in that
|
||||||
|
it does not pass promises through, nor coerces promises from other
|
||||||
|
systems. The promise becomes the fulfillment value. This is only
|
||||||
|
recommended for use when trying to fulfill a promise with an object that has
|
||||||
|
a `then` function that is at the same time not a promise.
|
||||||
|
|
||||||
|
## 0.8.12
|
||||||
|
- Treat foreign promises as unresolved in `Q.isFulfilled`; this lets `Q.all`
|
||||||
|
work on arrays containing foreign promises. #154
|
||||||
|
- Fix minor incompliances with the [Promises/A+ spec][] and [test suite][]. #157
|
||||||
|
#158
|
||||||
|
|
||||||
|
[Promises/A+ spec]: http://promises-aplus.github.com/promises-spec/
|
||||||
|
[test suite]: https://github.com/promises-aplus/promises-tests
|
||||||
|
|
||||||
|
## 0.8.11
|
||||||
|
|
||||||
|
- Added ``nfcall``, ``nfapply``, and ``nfbind`` as ``thisp``-less versions of
|
||||||
|
``ncall``, ``napply``, and ``nbind``. The latter are now deprecated. #142
|
||||||
|
- Long stack traces no longer cause linearly-growing memory usage when chaining
|
||||||
|
promises together. #111
|
||||||
|
- Inspecting ``error.stack`` in a rejection handler will now give a long stack
|
||||||
|
trace. #103
|
||||||
|
- Fixed ``Q.timeout`` to clear its timeout handle when the promise is rejected;
|
||||||
|
previously, it kept the event loop alive until the timeout period expired.
|
||||||
|
#145 @dfilatov
|
||||||
|
- Added `q/queue` module, which exports an infinite promise queue
|
||||||
|
constructor.
|
||||||
|
|
||||||
|
## 0.8.10
|
||||||
|
|
||||||
|
- Added ``done`` as a replacement for ``end``, taking the usual fulfillment,
|
||||||
|
rejection, and progress handlers. It's essentially equivalent to
|
||||||
|
``then(f, r, p).end()``.
|
||||||
|
- Added ``Q.onerror``, a settable error trap that you can use to get full stack
|
||||||
|
traces for uncaught errors. #94
|
||||||
|
- Added ``thenResolve`` as a shortcut for returning a constant value once a
|
||||||
|
promise is fulfilled. #108 @ForbesLindesay
|
||||||
|
- Various tweaks to progress notification, including propagation and
|
||||||
|
transformation of progress values and only forwarding a single progress
|
||||||
|
object.
|
||||||
|
- Renamed ``nend`` to ``nodeify``. It no longer returns an always-fulfilled
|
||||||
|
promise when a Node callback is passed.
|
||||||
|
- ``deferred.resolve`` and ``deferred.reject`` no longer (sometimes) return
|
||||||
|
``deferred.promise``.
|
||||||
|
- Fixed stack traces getting mangled if they hit ``end`` twice. #116 #121 @ef4
|
||||||
|
- Fixed ``ninvoke`` and ``npost`` to work on promises for objects with Node
|
||||||
|
methods. #134
|
||||||
|
- Fixed accidental coercion of objects with nontrivial ``valueOf`` methods,
|
||||||
|
like ``Date``s, by the promise's ``valueOf`` method. #135
|
||||||
|
- Fixed ``spread`` not calling the passed rejection handler if given a rejected
|
||||||
|
promise.
|
||||||
|
|
||||||
|
## 0.8.9
|
||||||
|
|
||||||
|
- Added ``nend``
|
||||||
|
- Added preliminary progress notification support, via
|
||||||
|
``promise.then(onFulfilled, onRejected, onProgress)``,
|
||||||
|
``promise.progress(onProgress)``, and ``deferred.notify(...progressData)``.
|
||||||
|
- Made ``put`` and ``del`` return the object acted upon for easier chaining.
|
||||||
|
#84
|
||||||
|
- Fixed coercion cycles with cooperating promises. #106
|
||||||
|
|
||||||
|
## 0.8.7
|
||||||
|
|
||||||
|
- Support [Montage Require](http://github.com/kriskowal/mr)
|
||||||
|
|
||||||
|
## 0.8.6
|
||||||
|
|
||||||
|
- Fixed ``npost`` and ``ninvoke`` to pass the correct ``thisp``. #74
|
||||||
|
- Fixed various cases involving unorthodox rejection reasons. #73 #90
|
||||||
|
@ef4
|
||||||
|
- Fixed double-resolving of misbehaved custom promises. #75
|
||||||
|
- Sped up ``Q.all`` for arrays contain already-resolved promises or scalar
|
||||||
|
values. @ForbesLindesay
|
||||||
|
- Made stack trace filtering work when concatenating assets. #93 @ef4
|
||||||
|
- Added warnings for deprecated methods. @ForbesLindesay
|
||||||
|
- Added ``.npmignore`` file so that dependent packages get a slimmer
|
||||||
|
``node_modules`` directory.
|
||||||
|
|
||||||
|
## 0.8.5
|
||||||
|
|
||||||
|
- Added preliminary support for long traces (@domenic)
|
||||||
|
- Added ``fapply``, ``fcall``, ``fbind`` for non-thisp
|
||||||
|
promised function calls.
|
||||||
|
- Added ``return`` for async generators, where generators
|
||||||
|
are implemented.
|
||||||
|
- Rejected promises now have an "exception" property. If an object
|
||||||
|
isRejected(object), then object.valueOf().exception will
|
||||||
|
be the wrapped error.
|
||||||
|
- Added Jasmine specifications
|
||||||
|
- Support Internet Explorers 7–9 (with multiple bug fixes @domenic)
|
||||||
|
- Support Firefox 12
|
||||||
|
- Support Safari 5.1.5
|
||||||
|
- Support Chrome 18
|
||||||
|
|
||||||
|
## 0.8.4
|
||||||
|
|
||||||
|
- WARNING: ``promise.timeout`` is now rejected with an ``Error`` object
|
||||||
|
and the message now includes the duration of the timeout in
|
||||||
|
miliseconds. This doesn't constitute (in my opinion) a
|
||||||
|
backward-incompatibility since it is a change of an undocumented and
|
||||||
|
unspecified public behavior, but if you happened to depend on the
|
||||||
|
exception being a string, you will need to revise your code.
|
||||||
|
- Added ``deferred.makeNodeResolver()`` to replace the more cryptic
|
||||||
|
``deferred.node()`` method.
|
||||||
|
- Added experimental ``Q.promise(maker(resolve, reject))`` to make a
|
||||||
|
promise inside a callback, such that thrown exceptions in the
|
||||||
|
callback are converted and the resolver and rejecter are arguments.
|
||||||
|
This is a shorthand for making a deferred directly and inspired by
|
||||||
|
@gozala’s stream constructor pattern and the Microsoft Windows Metro
|
||||||
|
Promise constructor interface.
|
||||||
|
- Added experimental ``Q.begin()`` that is intended to kick off chains
|
||||||
|
of ``.then`` so that each of these can be reordered without having to
|
||||||
|
edit the new and former first step.
|
||||||
|
|
||||||
|
## 0.8.3
|
||||||
|
|
||||||
|
- Added ``isFulfilled``, ``isRejected``, and ``isResolved``
|
||||||
|
to the promise prototype.
|
||||||
|
- Added ``allResolved`` for waiting for every promise to either be
|
||||||
|
fulfilled or rejected, without propagating an error. @utvara #53
|
||||||
|
- Added ``Q.bind`` as a method to transform functions that
|
||||||
|
return and throw into promise-returning functions. See
|
||||||
|
[an example](https://gist.github.com/1782808). @domenic
|
||||||
|
- Renamed ``node`` export to ``nbind``, and added ``napply`` to
|
||||||
|
complete the set. ``node`` remains as deprecated. @domenic #58
|
||||||
|
- Renamed ``Method`` export to ``sender``. ``Method``
|
||||||
|
remains as deprecated and will be removed in the next
|
||||||
|
major version since I expect it has very little usage.
|
||||||
|
- Added browser console message indicating a live list of
|
||||||
|
unhandled errors.
|
||||||
|
- Added support for ``msSetImmediate`` (IE10) or ``setImmediate``
|
||||||
|
(available via [polyfill](https://github.com/NobleJS/setImmediate))
|
||||||
|
as a browser-side ``nextTick`` implementation. #44 #50 #59
|
||||||
|
- Stopped using the event-queue dependency, which was in place for
|
||||||
|
Narwhal support: now directly using ``process.nextTick``.
|
||||||
|
- WARNING: EXPERIMENTAL: added ``finally`` alias for ``fin``, ``catch``
|
||||||
|
alias for ``fail``, ``try`` alias for ``call``, and ``delete`` alias
|
||||||
|
for ``del``. These properties are enquoted in the library for
|
||||||
|
cross-browser compatibility, but may be used as property names in
|
||||||
|
modern engines.
|
||||||
|
|
||||||
|
## 0.8.2
|
||||||
|
|
||||||
|
- Deprecated ``ref`` in favor of ``resolve`` as recommended by
|
||||||
|
@domenic.
|
||||||
|
- Update event-queue dependency.
|
||||||
|
|
||||||
|
## 0.8.1
|
||||||
|
|
||||||
|
- Fixed Opera bug. #35 @cadorn
|
||||||
|
- Fixed ``Q.all([])`` #32 @domenic
|
||||||
|
|
||||||
|
## 0.8.0
|
||||||
|
|
||||||
|
- WARNING: ``enqueue`` removed. Use ``nextTick`` instead.
|
||||||
|
This is more consistent with NodeJS and (subjectively)
|
||||||
|
more explicit and intuitive.
|
||||||
|
- WARNING: ``def`` removed. Use ``master`` instead. The
|
||||||
|
term ``def`` was too confusing to new users.
|
||||||
|
- WARNING: ``spy`` removed in favor of ``fin``.
|
||||||
|
- WARNING: ``wait`` removed. Do ``all(args).get(0)`` instead.
|
||||||
|
- WARNING: ``join`` removed. Do ``all(args).spread(callback)`` instead.
|
||||||
|
- WARNING: Removed the ``Q`` function module.exports alias
|
||||||
|
for ``Q.ref``. It conflicts with ``Q.apply`` in weird
|
||||||
|
ways, making it uncallable.
|
||||||
|
- Revised ``delay`` so that it accepts both ``(value,
|
||||||
|
timeout)`` and ``(timeout)`` variations based on
|
||||||
|
arguments length.
|
||||||
|
- Added ``ref().spread(cb(...args))``, a variant of
|
||||||
|
``then`` that spreads an array across multiple arguments.
|
||||||
|
Useful with ``all()``.
|
||||||
|
- Added ``defer().node()`` Node callback generator. The
|
||||||
|
callback accepts ``(error, value)`` or ``(error,
|
||||||
|
...values)``. For multiple value arguments, the
|
||||||
|
fulfillment value is an array, useful in conjunction with
|
||||||
|
``spread``.
|
||||||
|
- Added ``node`` and ``ncall``, both with the signature
|
||||||
|
``(fun, thisp_opt, ...args)``. The former is a decorator
|
||||||
|
and the latter calls immediately. ``node`` optional
|
||||||
|
binds and partially applies. ``ncall`` can bind and pass
|
||||||
|
arguments.
|
||||||
|
|
||||||
|
## 0.7.2
|
||||||
|
|
||||||
|
- Fixed thenable promise assimilation.
|
||||||
|
|
||||||
|
## 0.7.1
|
||||||
|
|
||||||
|
- Stopped shimming ``Array.prototype.reduce``. The
|
||||||
|
enumerable property has bad side-effects. Libraries that
|
||||||
|
depend on this (for example, QQ) will need to be revised.
|
||||||
|
|
||||||
|
## 0.7.0 - BACKWARD INCOMPATIBILITY
|
||||||
|
|
||||||
|
- WARNING: Removed ``report`` and ``asap``
|
||||||
|
- WARNING: The ``callback`` argument of the ``fin``
|
||||||
|
function no longer receives any arguments. Thus, it can
|
||||||
|
be used to call functions that should not receive
|
||||||
|
arguments on resolution. Use ``when``, ``then``, or
|
||||||
|
``fail`` if you need a value.
|
||||||
|
- IMPORTANT: Fixed a bug in the use of ``MessageChannel``
|
||||||
|
for ``nextTick``.
|
||||||
|
- Renamed ``enqueue`` to ``nextTick``.
|
||||||
|
- Added experimental ``view`` and ``viewInfo`` for creating
|
||||||
|
views of promises either when or before they're
|
||||||
|
fulfilled.
|
||||||
|
- Shims are now externally applied so subsequent scripts or
|
||||||
|
dependees can use them.
|
||||||
|
- Improved minification results.
|
||||||
|
- Improved readability.
|
||||||
|
|
||||||
|
## 0.6.0 - BACKWARD INCOMPATIBILITY
|
||||||
|
|
||||||
|
- WARNING: In practice, the implementation of ``spy`` and
|
||||||
|
the name ``fin`` were useful. I've removed the old
|
||||||
|
``fin`` implementation and renamed/aliased ``spy``.
|
||||||
|
- The "q" module now exports its ``ref`` function as a "Q"
|
||||||
|
constructor, with module systems that support exports
|
||||||
|
assignment including NodeJS, RequireJS, and when used as
|
||||||
|
a ``<script>`` tag. Notably, strictly compliant CommonJS
|
||||||
|
does not support this, but UncommonJS does.
|
||||||
|
- Added ``async`` decorator for generators that use yield
|
||||||
|
to "trampoline" promises. In engines that support
|
||||||
|
generators (SpiderMonkey), this will greatly reduce the
|
||||||
|
need for nested callbacks.
|
||||||
|
- Made ``when`` chainable.
|
||||||
|
- Made ``all`` chainable.
|
||||||
|
|
||||||
|
## 0.5.3
|
||||||
|
|
||||||
|
- Added ``all`` and refactored ``join`` and ``wait`` to use
|
||||||
|
it. All of these will now reject at the earliest
|
||||||
|
rejection.
|
||||||
|
|
||||||
|
## 0.5.2
|
||||||
|
|
||||||
|
- Minor improvement to ``spy``; now waits for resolution of
|
||||||
|
callback promise.
|
||||||
|
|
||||||
|
## 0.5.1
|
||||||
|
|
||||||
|
- Made most Q API methods chainable on promise objects, and
|
||||||
|
turned the previous promise-methods of ``join``,
|
||||||
|
``wait``, and ``report`` into Q API methods.
|
||||||
|
- Added ``apply`` and ``call`` to the Q API, and ``apply``
|
||||||
|
as a promise handler.
|
||||||
|
- Added ``fail``, ``fin``, and ``spy`` to Q and the promise
|
||||||
|
prototype for convenience when observing rejection,
|
||||||
|
fulfillment and rejection, or just observing without
|
||||||
|
affecting the resolution.
|
||||||
|
- Renamed ``def`` (although ``def`` remains shimmed until
|
||||||
|
the next major release) to ``master``.
|
||||||
|
- Switched to using ``MessageChannel`` for next tick task
|
||||||
|
enqueue in browsers that support it.
|
||||||
|
|
||||||
|
## 0.5.0 - MINOR BACKWARD INCOMPATIBILITY
|
||||||
|
|
||||||
|
- Exceptions are no longer reported when consumed.
|
||||||
|
- Removed ``error`` from the API. Since exceptions are
|
||||||
|
getting consumed, throwing them in an errback causes the
|
||||||
|
exception to silently disappear. Use ``end``.
|
||||||
|
- Added ``end`` as both an API method and a promise-chain
|
||||||
|
ending method. It causes propagated rejections to be
|
||||||
|
thrown, which allows Node to write stack traces and
|
||||||
|
emit ``uncaughtException`` events, and browsers to
|
||||||
|
likewise emit ``onerror`` and log to the console.
|
||||||
|
- Added ``join`` and ``wait`` as promise chain functions,
|
||||||
|
so you can wait for variadic promises, returning your own
|
||||||
|
promise back, or join variadic promises, resolving with a
|
||||||
|
callback that receives variadic fulfillment values.
|
||||||
|
|
||||||
|
## 0.4.4
|
||||||
|
|
||||||
|
- ``end`` no longer returns a promise. It is the end of the
|
||||||
|
promise chain.
|
||||||
|
- Stopped reporting thrown exceptions in ``when`` callbacks
|
||||||
|
and errbacks. These must be explicitly reported through
|
||||||
|
``.end()``, ``.then(null, Q.error)``, or some other
|
||||||
|
mechanism.
|
||||||
|
- Added ``report`` as an API method, which can be used as
|
||||||
|
an errback to report and propagate an error.
|
||||||
|
- Added ``report`` as a promise-chain method, so an error
|
||||||
|
can be reported if it passes such a gate.
|
||||||
|
|
||||||
|
## 0.4.3
|
||||||
|
|
||||||
|
- Fixed ``<script>`` support that regressed with 0.4.2
|
||||||
|
because of "use strict" in the module system
|
||||||
|
multi-plexer.
|
||||||
|
|
||||||
|
## 0.4.2
|
||||||
|
|
||||||
|
- Added support for RequireJS (jburke)
|
||||||
|
|
||||||
|
## 0.4.1
|
||||||
|
|
||||||
|
- Added an "end" method to the promise prototype,
|
||||||
|
as a shorthand for waiting for the promise to
|
||||||
|
be resolved gracefully, and failing to do so,
|
||||||
|
to dump an error message.
|
||||||
|
|
||||||
|
## 0.4.0 - BACKWARD INCOMPATIBLE*
|
||||||
|
|
||||||
|
- *Removed the utility modules. NPM and Node no longer
|
||||||
|
expose any module except the main module. These have
|
||||||
|
been moved and merged into the "qq" package.
|
||||||
|
- *In a non-CommonJS browser, q.js can be used as a script.
|
||||||
|
It now creates a Q global variable.
|
||||||
|
- Fixed thenable assimilation.
|
||||||
|
- Fixed some issues with asap, when it resolves to
|
||||||
|
undefined, or throws an exception.
|
||||||
|
|
||||||
|
## 0.3.0 - BACKWARD-INCOMPATIBLE
|
||||||
|
|
||||||
|
- The `post` method has been reverted to its original
|
||||||
|
signature, as provided in Tyler Close's `ref_send` API.
|
||||||
|
That is, `post` accepts two arguments, the second of
|
||||||
|
which is an arbitrary object, but usually invocation
|
||||||
|
arguments as an `Array`. To provide variadic arguments
|
||||||
|
to `post`, there is a new `invoke` function that posts
|
||||||
|
the variadic arguments to the value given in the first
|
||||||
|
argument.
|
||||||
|
- The `defined` method has been moved from `q` to `q/util`
|
||||||
|
since it gets no use in practice but is still
|
||||||
|
theoretically useful.
|
||||||
|
- The `Promise` constructor has been renamed to
|
||||||
|
`makePromise` to be consistent with the convention that
|
||||||
|
functions that do not require the `new` keyword to be
|
||||||
|
used as constructors have camelCase names.
|
||||||
|
- The `isResolved` function has been renamed to
|
||||||
|
`isFulfilled`. There is a new `isResolved` function that
|
||||||
|
indicates whether a value is not a promise or, if it is a
|
||||||
|
promise, whether it has been either fulfilled or
|
||||||
|
rejected. The code has been revised to reflect this
|
||||||
|
nuance in terminology.
|
||||||
|
|
||||||
|
## 0.2.10
|
||||||
|
|
||||||
|
- Added `join` to `"q/util"` for variadically joining
|
||||||
|
multiple promises.
|
||||||
|
|
||||||
|
## 0.2.9
|
||||||
|
|
||||||
|
- The future-compatible `invoke` method has been added,
|
||||||
|
to replace `post`, since `post` will become backward-
|
||||||
|
incompatible in the next major release.
|
||||||
|
- Exceptions thrown in the callbacks of a `when` call are
|
||||||
|
now emitted to Node's `"uncaughtException"` `process`
|
||||||
|
event in addition to being returned as a rejection reason.
|
||||||
|
|
||||||
|
## 0.2.8
|
||||||
|
|
||||||
|
- Exceptions thrown in the callbacks of a `when` call
|
||||||
|
are now consumed, warned, and transformed into
|
||||||
|
rejections of the promise returned by `when`.
|
||||||
|
|
||||||
|
## 0.2.7
|
||||||
|
|
||||||
|
- Fixed a minor bug in thenable assimilation, regressed
|
||||||
|
because of the change in the forwarding protocol.
|
||||||
|
- Fixed behavior of "q/util" `deep` method on dates and
|
||||||
|
other primitives. Github issue #11.
|
||||||
|
|
||||||
|
## 0.2.6
|
||||||
|
|
||||||
|
- Thenables (objects with a "then" method) are accepted
|
||||||
|
and provided, bringing this implementation of Q
|
||||||
|
into conformance with Promises/A, B, and D.
|
||||||
|
- Added `makePromise`, to replace the `Promise` function
|
||||||
|
eventually.
|
||||||
|
- Rejections are now also duck-typed. A rejection is a
|
||||||
|
promise with a valueOf method that returns a rejection
|
||||||
|
descriptor. A rejection descriptor has a
|
||||||
|
"promiseRejected" property equal to "true" and a
|
||||||
|
"reason" property corresponding to the rejection reason.
|
||||||
|
- Altered the `makePromise` API such that the `fallback`
|
||||||
|
method no longer receives a superfluous `resolved` method
|
||||||
|
after the `operator`. The fallback method is responsible
|
||||||
|
only for returning a resolution. This breaks an
|
||||||
|
undocumented API, so third-party API's depending on the
|
||||||
|
previous undocumented behavior may break.
|
||||||
|
|
||||||
|
## 0.2.5
|
||||||
|
|
||||||
|
- Changed promises into a duck-type such that multiple
|
||||||
|
instances of the Q module can exchange promise objects.
|
||||||
|
A promise is now defined as "an object that implements the
|
||||||
|
`promiseSend(op, resolved, ...)` method and `valueOf`".
|
||||||
|
- Exceptions in promises are now captured and returned
|
||||||
|
as rejections.
|
||||||
|
|
||||||
|
## 0.2.4
|
||||||
|
|
||||||
|
- Fixed bug in `ref` that prevented `del` messages from
|
||||||
|
being received (gozala)
|
||||||
|
- Fixed a conflict with FireFox 4; constructor property
|
||||||
|
is now read-only.
|
||||||
|
|
||||||
|
## 0.2.3
|
||||||
|
|
||||||
|
- Added `keys` message to promises and to the promise API.
|
||||||
|
|
||||||
|
## 0.2.2
|
||||||
|
|
||||||
|
- Added boilerplate to `q/queue` and `q/util`.
|
||||||
|
- Fixed missing dependency to `q/queue`.
|
||||||
|
|
||||||
|
## 0.2.1
|
||||||
|
|
||||||
|
- The `resolve` and `reject` methods of `defer` objects now
|
||||||
|
return the resolution promise for convenience.
|
||||||
|
- Added `q/util`, which provides `step`, `delay`, `shallow`,
|
||||||
|
`deep`, and three reduction orders.
|
||||||
|
- Added `q/queue` module for a promise `Queue`.
|
||||||
|
- Added `q-comm` to the list of compatible libraries.
|
||||||
|
- Deprecated `defined` from `q`, with intent to move it to
|
||||||
|
`q/util`.
|
||||||
|
|
||||||
|
## 0.2.0 - BACKWARD INCOMPATIBLE
|
||||||
|
|
||||||
|
- Changed post(ref, name, args) to variadic
|
||||||
|
post(ref, name, ...args). BACKWARD INCOMPATIBLE
|
||||||
|
- Added a def(value) method to annotate an object as being
|
||||||
|
necessarily a local value that cannot be serialized, such
|
||||||
|
that inter-process/worker/vat promise communication
|
||||||
|
libraries will send messages to it, but never send it
|
||||||
|
back.
|
||||||
|
- Added a send(value, op, ...args) method to the public API, for
|
||||||
|
forwarding messages to a value or promise in a future turn.
|
||||||
|
|
||||||
|
## 0.1.9
|
||||||
|
|
||||||
|
- Added isRejected() for testing whether a value is a rejected
|
||||||
|
promise. isResolved() retains the behavior of stating
|
||||||
|
that rejected promises are not resolved.
|
||||||
|
|
||||||
|
## 0.1.8
|
||||||
|
|
||||||
|
- Fixed isResolved(null) and isResolved(undefined) [issue #9]
|
||||||
|
- Fixed a problem with the Object.create shim
|
||||||
|
|
||||||
|
## 0.1.7
|
||||||
|
|
||||||
|
- shimmed ES5 Object.create in addition to Object.freeze
|
||||||
|
for compatibility on non-ES5 engines (gozala)
|
||||||
|
|
||||||
|
## 0.1.6
|
||||||
|
|
||||||
|
- Q.isResolved added
|
||||||
|
- promise.valueOf() now returns the value of resolved
|
||||||
|
and near values
|
||||||
|
- asap retried
|
||||||
|
- promises are frozen when possible
|
||||||
|
|
||||||
|
## 0.1.5
|
||||||
|
|
||||||
|
- fixed dependency list for Teleport (gozala)
|
||||||
|
- all unit tests now pass (gozala)
|
||||||
|
|
||||||
|
## 0.1.4
|
||||||
|
|
||||||
|
- added support for Teleport as an engine (gozala)
|
||||||
|
- simplified and updated methods for getting internal
|
||||||
|
print and enqueue functions universally (gozala)
|
||||||
|
|
||||||
|
## 0.1.3
|
||||||
|
|
||||||
|
- fixed erroneous link to the q module in package.json
|
||||||
|
|
||||||
|
## 0.1.2
|
||||||
|
|
||||||
|
- restructured for overlay style package compatibility
|
||||||
|
|
||||||
|
## 0.1.0
|
||||||
|
|
||||||
|
- removed asap because it was broken, probably down to the
|
||||||
|
philosophy.
|
||||||
|
|
||||||
|
## 0.0.3
|
||||||
|
|
||||||
|
- removed q-util
|
||||||
|
- fixed asap so it returns a value if completed
|
||||||
|
|
||||||
|
## 0.0.2
|
||||||
|
|
||||||
|
- added q-util
|
||||||
|
|
||||||
|
## 0.0.1
|
||||||
|
|
||||||
|
- initial version
|
3
bin/node_modules/q/LICENSE → node_modules/q/LICENSE
generated
vendored
3
bin/node_modules/q/LICENSE → node_modules/q/LICENSE
generated
vendored
@ -1,5 +1,4 @@
|
|||||||
|
Copyright 2009–2014 Kristopher Michael Kowal. All rights reserved.
|
||||||
Copyright 2009–2012 Kristopher Michael Kowal. All rights reserved.
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to
|
of this software and associated documentation files (the "Software"), to
|
||||||
deal in the Software without restriction, including without limitation the
|
deal in the Software without restriction, including without limitation the
|
88
bin/node_modules/q/README.md → node_modules/q/README.md
generated
vendored
88
bin/node_modules/q/README.md → node_modules/q/README.md
generated
vendored
@ -1,10 +1,17 @@
|
|||||||
[](http://travis-ci.org/kriskowal/q)
|
[](http://travis-ci.org/kriskowal/q)
|
||||||
|
|
||||||
<a href="http://promises-aplus.github.com/promises-spec">
|
<a href="http://promises-aplus.github.com/promises-spec">
|
||||||
<img src="http://promises-aplus.github.com/promises-spec/assets/logo-small.png"
|
<img src="http://kriskowal.github.io/q/q.png"
|
||||||
align="right" alt="Promises/A+ logo" />
|
align="right" alt="Q logo" />
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
*This is Q version 1, from the `v1` branch in Git. This documentation applies to
|
||||||
|
the latest of both the version 1 and version 0.9 release trains. These releases
|
||||||
|
are stable. There will be no further releases of 0.9 after 0.9.7 which is nearly
|
||||||
|
equivalent to version 1.0.0. All further releases of `q@~1.0` will be backward
|
||||||
|
compatible. The version 2 release train introduces significant and
|
||||||
|
backward-incompatible changes and is experimental at this time.*
|
||||||
|
|
||||||
If a function cannot return a value or throw an exception without
|
If a function cannot return a value or throw an exception without
|
||||||
blocking, it can return a promise instead. A promise is an object
|
blocking, it can return a promise instead. A promise is an object
|
||||||
that represents the return value or the thrown exception that the
|
that represents the return value or the thrown exception that the
|
||||||
@ -73,7 +80,7 @@ The Q module can be loaded as:
|
|||||||
the [q](https://npmjs.org/package/q) package
|
the [q](https://npmjs.org/package/q) package
|
||||||
- An AMD module
|
- An AMD module
|
||||||
- A [component](https://github.com/component/component) as ``microjs/q``
|
- A [component](https://github.com/component/component) as ``microjs/q``
|
||||||
- Using [bower](http://bower.io/) as ``q``
|
- Using [bower](http://bower.io/) as `q#1.0.1`
|
||||||
- Using [NuGet](http://nuget.org/) as [Q](https://nuget.org/packages/q)
|
- Using [NuGet](http://nuget.org/) as [Q](https://nuget.org/packages/q)
|
||||||
|
|
||||||
Q can exchange promises with jQuery, Dojo, When.js, WinJS, and more.
|
Q can exchange promises with jQuery, Dojo, When.js, WinJS, and more.
|
||||||
@ -287,7 +294,7 @@ If you have a promise for an array, you can use ``spread`` as a
|
|||||||
replacement for ``then``. The ``spread`` function “spreads” the
|
replacement for ``then``. The ``spread`` function “spreads” the
|
||||||
values over the arguments of the fulfillment handler. The rejection handler
|
values over the arguments of the fulfillment handler. The rejection handler
|
||||||
will get called at the first sign of failure. That is, whichever of
|
will get called at the first sign of failure. That is, whichever of
|
||||||
the recived promises fails first gets handled by the rejection handler.
|
the received promises fails first gets handled by the rejection handler.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
function eventualAdd(a, b) {
|
function eventualAdd(a, b) {
|
||||||
@ -328,6 +335,18 @@ Q.allSettled(promises)
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The ``any`` function accepts an array of promises and returns a promise that is
|
||||||
|
fulfilled by the first given promise to be fulfilled, or rejected if all of the
|
||||||
|
given promises are rejected.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
Q.any(promises)
|
||||||
|
.then(function (first) {
|
||||||
|
// Any of the promises was fulfilled.
|
||||||
|
}, function (error) {
|
||||||
|
// All of the promises were rejected.
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
### Sequences
|
### Sequences
|
||||||
|
|
||||||
@ -359,16 +378,16 @@ return funcs.reduce(function (soFar, f) {
|
|||||||
}, Q(initialVal));
|
}, Q(initialVal));
|
||||||
```
|
```
|
||||||
|
|
||||||
Or, you could use th ultra-compact version:
|
Or, you could use the ultra-compact version:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
return funcs.reduce(Q.when, Q());
|
return funcs.reduce(Q.when, Q(initialVal));
|
||||||
```
|
```
|
||||||
|
|
||||||
### Handling Errors
|
### Handling Errors
|
||||||
|
|
||||||
One sometimes-unintuive aspect of promises is that if you throw an
|
One sometimes-unintuive aspect of promises is that if you throw an
|
||||||
exception in the fulfillment handler, it will not be be caught by the error
|
exception in the fulfillment handler, it will not be caught by the error
|
||||||
handler.
|
handler.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
@ -603,6 +622,46 @@ requestOkText("http://localhost:3000")
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Using `Q.Promise`
|
||||||
|
|
||||||
|
This is an alternative promise-creation API that has the same power as
|
||||||
|
the deferred concept, but without introducing another conceptual entity.
|
||||||
|
|
||||||
|
Rewriting the `requestOkText` example above using `Q.Promise`:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
function requestOkText(url) {
|
||||||
|
return Q.Promise(function(resolve, reject, notify) {
|
||||||
|
var request = new XMLHttpRequest();
|
||||||
|
|
||||||
|
request.open("GET", url, true);
|
||||||
|
request.onload = onload;
|
||||||
|
request.onerror = onerror;
|
||||||
|
request.onprogress = onprogress;
|
||||||
|
request.send();
|
||||||
|
|
||||||
|
function onload() {
|
||||||
|
if (request.status === 200) {
|
||||||
|
resolve(request.responseText);
|
||||||
|
} else {
|
||||||
|
reject(new Error("Status code was " + request.status));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onerror() {
|
||||||
|
reject(new Error("Can't XHR " + JSON.stringify(url)));
|
||||||
|
}
|
||||||
|
|
||||||
|
function onprogress(event) {
|
||||||
|
notify(event.loaded / event.total);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
If `requestOkText` were to throw an exception, the returned promise would be
|
||||||
|
rejected with that thrown exception as the rejection reason.
|
||||||
|
|
||||||
### The Middle
|
### The Middle
|
||||||
|
|
||||||
If you are using a function that may return a promise, but just might
|
If you are using a function that may return a promise, but just might
|
||||||
@ -791,11 +850,20 @@ From previous event:
|
|||||||
at Object.<anonymous> (/path/to/test.js:7:1)
|
at Object.<anonymous> (/path/to/test.js:7:1)
|
||||||
```
|
```
|
||||||
|
|
||||||
Note how you can see the the function that triggered the async operation in the
|
Note how you can see the function that triggered the async operation in the
|
||||||
stack trace! This is very helpful for debugging, as otherwise you end up getting
|
stack trace! This is very helpful for debugging, as otherwise you end up getting
|
||||||
only the first line, plus a bunch of Q internals, with no sign of where the
|
only the first line, plus a bunch of Q internals, with no sign of where the
|
||||||
operation started.
|
operation started.
|
||||||
|
|
||||||
|
In node.js, this feature can also be enabled through the Q_DEBUG environment
|
||||||
|
variable:
|
||||||
|
|
||||||
|
```
|
||||||
|
Q_DEBUG=1 node server.js
|
||||||
|
```
|
||||||
|
|
||||||
|
This will enable long stack support in every instance of Q.
|
||||||
|
|
||||||
This feature does come with somewhat-serious performance and memory overhead,
|
This feature does come with somewhat-serious performance and memory overhead,
|
||||||
however. If you're working with lots of promises, or trying to scale a server
|
however. If you're working with lots of promises, or trying to scale a server
|
||||||
to many users, you should probably keep it off. But in development, go for it!
|
to many users, you should probably keep it off. But in development, go for it!
|
||||||
@ -804,10 +872,10 @@ to many users, you should probably keep it off. But in development, go for it!
|
|||||||
|
|
||||||
You can view the results of the Q test suite [in your browser][tests]!
|
You can view the results of the Q test suite [in your browser][tests]!
|
||||||
|
|
||||||
[tests]: https://rawgithub.com/kriskowal/q/master/spec/q-spec.html
|
[tests]: https://rawgithub.com/kriskowal/q/v1/spec/q-spec.html
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
Copyright 2009–2013 Kristopher Michael Kowal
|
Copyright 2009–2015 Kristopher Michael Kowal and contributors
|
||||||
MIT License (enclosed)
|
MIT License (enclosed)
|
||||||
|
|
120
node_modules/q/package.json
generated
vendored
Normal file
120
node_modules/q/package.json
generated
vendored
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
{
|
||||||
|
"name": "q",
|
||||||
|
"version": "1.4.1",
|
||||||
|
"description": "A library for promises (CommonJS/Promises/A,B,D)",
|
||||||
|
"homepage": "https://github.com/kriskowal/q",
|
||||||
|
"author": {
|
||||||
|
"name": "Kris Kowal",
|
||||||
|
"email": "kris@cixar.com",
|
||||||
|
"url": "https://github.com/kriskowal"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"q",
|
||||||
|
"promise",
|
||||||
|
"promises",
|
||||||
|
"promises-a",
|
||||||
|
"promises-aplus",
|
||||||
|
"deferred",
|
||||||
|
"future",
|
||||||
|
"async",
|
||||||
|
"flow control",
|
||||||
|
"fluent",
|
||||||
|
"browser",
|
||||||
|
"node"
|
||||||
|
],
|
||||||
|
"contributors": [
|
||||||
|
{
|
||||||
|
"name": "Kris Kowal",
|
||||||
|
"email": "kris@cixar.com",
|
||||||
|
"url": "https://github.com/kriskowal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Irakli Gozalishvili",
|
||||||
|
"email": "rfobic@gmail.com",
|
||||||
|
"url": "http://jeditoolkit.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Domenic Denicola",
|
||||||
|
"email": "domenic@domenicdenicola.com",
|
||||||
|
"url": "http://domenicdenicola.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"bugs": {
|
||||||
|
"url": "http://github.com/kriskowal/q/issues"
|
||||||
|
},
|
||||||
|
"license": {
|
||||||
|
"type": "MIT",
|
||||||
|
"url": "http://github.com/kriskowal/q/raw/master/LICENSE"
|
||||||
|
},
|
||||||
|
"main": "q.js",
|
||||||
|
"files": [
|
||||||
|
"LICENSE",
|
||||||
|
"q.js",
|
||||||
|
"queue.js"
|
||||||
|
],
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git://github.com/kriskowal/q.git"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.6.0",
|
||||||
|
"teleport": ">=0.2.0"
|
||||||
|
},
|
||||||
|
"dependencies": {},
|
||||||
|
"devDependencies": {
|
||||||
|
"cover": "*",
|
||||||
|
"grunt": "~0.4.1",
|
||||||
|
"grunt-cli": "~0.1.9",
|
||||||
|
"grunt-contrib-uglify": "~0.9.1",
|
||||||
|
"jasmine-node": "1.11.0",
|
||||||
|
"jshint": "~2.1.9",
|
||||||
|
"matcha": "~0.2.0",
|
||||||
|
"opener": "*",
|
||||||
|
"promises-aplus-tests": "1.x"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"test": "jasmine-node spec && promises-aplus-tests spec/aplus-adapter",
|
||||||
|
"test-browser": "opener spec/q-spec.html",
|
||||||
|
"benchmark": "matcha",
|
||||||
|
"lint": "jshint q.js",
|
||||||
|
"cover": "cover run jasmine-node spec && cover report html && opener cover_html/index.html",
|
||||||
|
"minify": "grunt",
|
||||||
|
"prepublish": "grunt"
|
||||||
|
},
|
||||||
|
"overlay": {
|
||||||
|
"teleport": {
|
||||||
|
"dependencies": {
|
||||||
|
"system": ">=0.0.4"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"directories": {
|
||||||
|
"test": "./spec"
|
||||||
|
},
|
||||||
|
"gitHead": "d373079d3620152e3d60e82f27265a09ee0e81bd",
|
||||||
|
"_id": "q@1.4.1",
|
||||||
|
"_shasum": "55705bcd93c5f3673530c2c2cbc0c2b3addc286e",
|
||||||
|
"_from": "q@1.4.1",
|
||||||
|
"_npmVersion": "2.8.3",
|
||||||
|
"_nodeVersion": "1.8.1",
|
||||||
|
"_npmUser": {
|
||||||
|
"name": "kriskowal",
|
||||||
|
"email": "kris.kowal@cixar.com"
|
||||||
|
},
|
||||||
|
"maintainers": [
|
||||||
|
{
|
||||||
|
"name": "kriskowal",
|
||||||
|
"email": "kris.kowal@cixar.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "domenic",
|
||||||
|
"email": "domenic@domenicdenicola.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dist": {
|
||||||
|
"shasum": "55705bcd93c5f3673530c2c2cbc0c2b3addc286e",
|
||||||
|
"tarball": "http://registry.npmjs.org/q/-/q-1.4.1.tgz"
|
||||||
|
},
|
||||||
|
"_resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz",
|
||||||
|
"readme": "ERROR: No README data found!"
|
||||||
|
}
|
359
bin/node_modules/q/q.js → node_modules/q/q.js
generated
vendored
359
bin/node_modules/q/q.js → node_modules/q/q.js
generated
vendored
@ -27,8 +27,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
(function (definition) {
|
(function (definition) {
|
||||||
// Turn off strict mode for this function so we can assign to global.Q
|
"use strict";
|
||||||
/* jshint strict: false */
|
|
||||||
|
|
||||||
// This file will function properly as a <script> tag, or a module
|
// This file will function properly as a <script> tag, or a module
|
||||||
// using CommonJS and NodeJS or RequireJS module formats. In
|
// using CommonJS and NodeJS or RequireJS module formats. In
|
||||||
@ -40,7 +39,7 @@
|
|||||||
bootstrap("promise", definition);
|
bootstrap("promise", definition);
|
||||||
|
|
||||||
// CommonJS
|
// CommonJS
|
||||||
} else if (typeof exports === "object") {
|
} else if (typeof exports === "object" && typeof module === "object") {
|
||||||
module.exports = definition();
|
module.exports = definition();
|
||||||
|
|
||||||
// RequireJS
|
// RequireJS
|
||||||
@ -56,8 +55,25 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// <script>
|
// <script>
|
||||||
|
} else if (typeof window !== "undefined" || typeof self !== "undefined") {
|
||||||
|
// Prefer window over self for add-on scripts. Use self for
|
||||||
|
// non-windowed contexts.
|
||||||
|
var global = typeof window !== "undefined" ? window : self;
|
||||||
|
|
||||||
|
// Get the `window` object, save the previous Q global
|
||||||
|
// and initialize Q as a global.
|
||||||
|
var previousQ = global.Q;
|
||||||
|
global.Q = definition();
|
||||||
|
|
||||||
|
// Add a noConflict function so Q can be removed from the
|
||||||
|
// global namespace.
|
||||||
|
global.Q.noConflict = function () {
|
||||||
|
global.Q = previousQ;
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Q = definition();
|
throw new Error("This environment was not anticipated by Q. Please file a bug.");
|
||||||
}
|
}
|
||||||
|
|
||||||
})(function () {
|
})(function () {
|
||||||
@ -89,57 +105,67 @@ var nextTick =(function () {
|
|||||||
var flushing = false;
|
var flushing = false;
|
||||||
var requestTick = void 0;
|
var requestTick = void 0;
|
||||||
var isNodeJS = false;
|
var isNodeJS = false;
|
||||||
|
// queue for late tasks, used by unhandled rejection tracking
|
||||||
|
var laterQueue = [];
|
||||||
|
|
||||||
function flush() {
|
function flush() {
|
||||||
/* jshint loopfunc: true */
|
/* jshint loopfunc: true */
|
||||||
|
var task, domain;
|
||||||
|
|
||||||
while (head.next) {
|
while (head.next) {
|
||||||
head = head.next;
|
head = head.next;
|
||||||
var task = head.task;
|
task = head.task;
|
||||||
head.task = void 0;
|
head.task = void 0;
|
||||||
var domain = head.domain;
|
domain = head.domain;
|
||||||
|
|
||||||
if (domain) {
|
if (domain) {
|
||||||
head.domain = void 0;
|
head.domain = void 0;
|
||||||
domain.enter();
|
domain.enter();
|
||||||
}
|
}
|
||||||
|
runSingle(task, domain);
|
||||||
|
|
||||||
try {
|
}
|
||||||
task();
|
while (laterQueue.length) {
|
||||||
|
task = laterQueue.pop();
|
||||||
|
runSingle(task);
|
||||||
|
}
|
||||||
|
flushing = false;
|
||||||
|
}
|
||||||
|
// runs a single function in the async queue
|
||||||
|
function runSingle(task, domain) {
|
||||||
|
try {
|
||||||
|
task();
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (isNodeJS) {
|
if (isNodeJS) {
|
||||||
// In node, uncaught exceptions are considered fatal errors.
|
// In node, uncaught exceptions are considered fatal errors.
|
||||||
// Re-throw them synchronously to interrupt flushing!
|
// Re-throw them synchronously to interrupt flushing!
|
||||||
|
|
||||||
// Ensure continuation if the uncaught exception is suppressed
|
// Ensure continuation if the uncaught exception is suppressed
|
||||||
// listening "uncaughtException" events (as domains does).
|
// listening "uncaughtException" events (as domains does).
|
||||||
// Continue in next event to avoid tick recursion.
|
// Continue in next event to avoid tick recursion.
|
||||||
if (domain) {
|
if (domain) {
|
||||||
domain.exit();
|
domain.exit();
|
||||||
}
|
}
|
||||||
setTimeout(flush, 0);
|
setTimeout(flush, 0);
|
||||||
if (domain) {
|
if (domain) {
|
||||||
domain.enter();
|
domain.enter();
|
||||||
}
|
|
||||||
|
|
||||||
throw e;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// In browsers, uncaught exceptions are not fatal.
|
|
||||||
// Re-throw them asynchronously to avoid slow-downs.
|
|
||||||
setTimeout(function() {
|
|
||||||
throw e;
|
|
||||||
}, 0);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (domain) {
|
throw e;
|
||||||
domain.exit();
|
|
||||||
|
} else {
|
||||||
|
// In browsers, uncaught exceptions are not fatal.
|
||||||
|
// Re-throw them asynchronously to avoid slow-downs.
|
||||||
|
setTimeout(function () {
|
||||||
|
throw e;
|
||||||
|
}, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
flushing = false;
|
if (domain) {
|
||||||
|
domain.exit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nextTick = function (task) {
|
nextTick = function (task) {
|
||||||
@ -155,9 +181,16 @@ var nextTick =(function () {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (typeof process !== "undefined" && process.nextTick) {
|
if (typeof process === "object" &&
|
||||||
// Node.js before 0.9. Note that some fake-Node environments, like the
|
process.toString() === "[object process]" && process.nextTick) {
|
||||||
// Mocha test runner, introduce a `process` global without a `nextTick`.
|
// Ensure Q is in a real Node environment, with a `process.nextTick`.
|
||||||
|
// To see through fake Node environments:
|
||||||
|
// * Mocha test runner - exposes a `process` global without a `nextTick`
|
||||||
|
// * Browserify - exposes a `process.nexTick` function that uses
|
||||||
|
// `setTimeout`. In this case `setImmediate` is preferred because
|
||||||
|
// it is faster. Browserify's `process.toString()` yields
|
||||||
|
// "[object Object]", while in a real Node environment
|
||||||
|
// `process.nextTick()` yields "[object process]".
|
||||||
isNodeJS = true;
|
isNodeJS = true;
|
||||||
|
|
||||||
requestTick = function () {
|
requestTick = function () {
|
||||||
@ -201,7 +234,16 @@ var nextTick =(function () {
|
|||||||
setTimeout(flush, 0);
|
setTimeout(flush, 0);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
// runs a task after all other tasks have been run
|
||||||
|
// this is useful for unhandled rejection tracking that needs to happen
|
||||||
|
// after all `then`d tasks have been run.
|
||||||
|
nextTick.runAfter = function (task) {
|
||||||
|
laterQueue.push(task);
|
||||||
|
if (!flushing) {
|
||||||
|
flushing = true;
|
||||||
|
requestTick();
|
||||||
|
}
|
||||||
|
};
|
||||||
return nextTick;
|
return nextTick;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
@ -211,9 +253,8 @@ var nextTick =(function () {
|
|||||||
// If you need a security guarantee, these primordials need to be
|
// If you need a security guarantee, these primordials need to be
|
||||||
// deeply frozen anyway, and if you don’t need a security guarantee,
|
// deeply frozen anyway, and if you don’t need a security guarantee,
|
||||||
// this is just plain paranoid.
|
// this is just plain paranoid.
|
||||||
// However, this does have the nice side-effect of reducing the size
|
// However, this **might** have the nice side-effect of reducing the size of
|
||||||
// of the code by reducing x.call() to merely x(), eliminating many
|
// the minified code by reducing x.call() to merely x()
|
||||||
// hard-to-minify characters.
|
|
||||||
// See Mark Miller’s explanation of what this does.
|
// See Mark Miller’s explanation of what this does.
|
||||||
// http://wiki.ecmascript.org/doku.php?id=conventions:safe_meta_programming
|
// http://wiki.ecmascript.org/doku.php?id=conventions:safe_meta_programming
|
||||||
var call = Function.call;
|
var call = Function.call;
|
||||||
@ -325,22 +366,6 @@ if (typeof ReturnValue !== "undefined") {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Until V8 3.19 / Chromium 29 is released, SpiderMonkey is the only
|
|
||||||
// engine that has a deployed base of browsers that support generators.
|
|
||||||
// However, SM's generators use the Python-inspired semantics of
|
|
||||||
// outdated ES6 drafts. We would like to support ES6, but we'd also
|
|
||||||
// like to make it possible to use generators in deployed browsers, so
|
|
||||||
// we also support Python-style generators. At some point we can remove
|
|
||||||
// this block.
|
|
||||||
var hasES6Generators;
|
|
||||||
try {
|
|
||||||
/* jshint evil: true, nonew: false */
|
|
||||||
new Function("(function* (){ yield 1; })");
|
|
||||||
hasES6Generators = true;
|
|
||||||
} catch (e) {
|
|
||||||
hasES6Generators = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// long stack traces
|
// long stack traces
|
||||||
|
|
||||||
var STACK_JUMP_SEPARATOR = "From previous event:";
|
var STACK_JUMP_SEPARATOR = "From previous event:";
|
||||||
@ -467,7 +492,7 @@ function Q(value) {
|
|||||||
// If the object is already a Promise, return it directly. This enables
|
// If the object is already a Promise, return it directly. This enables
|
||||||
// the resolve function to both be used to created references from objects,
|
// the resolve function to both be used to created references from objects,
|
||||||
// but to tolerably coerce non-promises to promises.
|
// but to tolerably coerce non-promises to promises.
|
||||||
if (isPromise(value)) {
|
if (value instanceof Promise) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -491,6 +516,11 @@ Q.nextTick = nextTick;
|
|||||||
*/
|
*/
|
||||||
Q.longStackSupport = false;
|
Q.longStackSupport = false;
|
||||||
|
|
||||||
|
// enable long stacks if Q_DEBUG is set
|
||||||
|
if (typeof process === "object" && process && process.env && process.env.Q_DEBUG) {
|
||||||
|
Q.longStackSupport = true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a {promise, resolve, reject} object.
|
* Constructs a {promise, resolve, reject} object.
|
||||||
*
|
*
|
||||||
@ -522,14 +552,14 @@ function defer() {
|
|||||||
progressListeners.push(operands[1]);
|
progressListeners.push(operands[1]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
nextTick(function () {
|
Q.nextTick(function () {
|
||||||
resolvedPromise.promiseDispatch.apply(resolvedPromise, args);
|
resolvedPromise.promiseDispatch.apply(resolvedPromise, args);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// XXX deprecated
|
// XXX deprecated
|
||||||
promise.valueOf = deprecate(function () {
|
promise.valueOf = function () {
|
||||||
if (messages) {
|
if (messages) {
|
||||||
return promise;
|
return promise;
|
||||||
}
|
}
|
||||||
@ -538,7 +568,7 @@ function defer() {
|
|||||||
resolvedPromise = nearerValue; // shorten chain
|
resolvedPromise = nearerValue; // shorten chain
|
||||||
}
|
}
|
||||||
return nearerValue;
|
return nearerValue;
|
||||||
}, "valueOf", "inspect");
|
};
|
||||||
|
|
||||||
promise.inspect = function () {
|
promise.inspect = function () {
|
||||||
if (!resolvedPromise) {
|
if (!resolvedPromise) {
|
||||||
@ -570,7 +600,7 @@ function defer() {
|
|||||||
promise.source = newPromise;
|
promise.source = newPromise;
|
||||||
|
|
||||||
array_reduce(messages, function (undefined, message) {
|
array_reduce(messages, function (undefined, message) {
|
||||||
nextTick(function () {
|
Q.nextTick(function () {
|
||||||
newPromise.promiseDispatch.apply(newPromise, message);
|
newPromise.promiseDispatch.apply(newPromise, message);
|
||||||
});
|
});
|
||||||
}, void 0);
|
}, void 0);
|
||||||
@ -608,7 +638,7 @@ function defer() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
array_reduce(progressListeners, function (undefined, progressListener) {
|
array_reduce(progressListeners, function (undefined, progressListener) {
|
||||||
nextTick(function () {
|
Q.nextTick(function () {
|
||||||
progressListener(progress);
|
progressListener(progress);
|
||||||
});
|
});
|
||||||
}, void 0);
|
}, void 0);
|
||||||
@ -641,6 +671,7 @@ defer.prototype.makeNodeResolver = function () {
|
|||||||
* @returns a promise that may be resolved with the given resolve and reject
|
* @returns a promise that may be resolved with the given resolve and reject
|
||||||
* functions, or rejected by a thrown exception in resolver
|
* functions, or rejected by a thrown exception in resolver
|
||||||
*/
|
*/
|
||||||
|
Q.Promise = promise; // ES6
|
||||||
Q.promise = promise;
|
Q.promise = promise;
|
||||||
function promise(resolver) {
|
function promise(resolver) {
|
||||||
if (typeof resolver !== "function") {
|
if (typeof resolver !== "function") {
|
||||||
@ -655,6 +686,11 @@ function promise(resolver) {
|
|||||||
return deferred.promise;
|
return deferred.promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
promise.race = race; // ES6
|
||||||
|
promise.all = all; // ES6
|
||||||
|
promise.reject = reject; // ES6
|
||||||
|
promise.resolve = Q; // ES6
|
||||||
|
|
||||||
// XXX experimental. This method is a way to denote that a local value is
|
// XXX experimental. This method is a way to denote that a local value is
|
||||||
// serializable and should be immediately dispatched to a remote upon request,
|
// serializable and should be immediately dispatched to a remote upon request,
|
||||||
// instead of passing a reference.
|
// instead of passing a reference.
|
||||||
@ -695,15 +731,15 @@ Promise.prototype.join = function (that) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a promise for the first of an array of promises to become fulfilled.
|
* Returns a promise for the first of an array of promises to become settled.
|
||||||
* @param answers {Array[Any*]} promises to race
|
* @param answers {Array[Any*]} promises to race
|
||||||
* @returns {Any*} the first promise to be fulfilled
|
* @returns {Any*} the first promise to be settled
|
||||||
*/
|
*/
|
||||||
Q.race = race;
|
Q.race = race;
|
||||||
function race(answerPs) {
|
function race(answerPs) {
|
||||||
return promise(function(resolve, reject) {
|
return promise(function (resolve, reject) {
|
||||||
// Switch to this once we can assume at least ES5
|
// Switch to this once we can assume at least ES5
|
||||||
// answerPs.forEach(function(answerP) {
|
// answerPs.forEach(function (answerP) {
|
||||||
// Q(answerP).then(resolve, reject);
|
// Q(answerP).then(resolve, reject);
|
||||||
// });
|
// });
|
||||||
// Use this in the meantime
|
// Use this in the meantime
|
||||||
@ -770,14 +806,14 @@ function Promise(descriptor, fallback, inspect) {
|
|||||||
promise.exception = inspected.reason;
|
promise.exception = inspected.reason;
|
||||||
}
|
}
|
||||||
|
|
||||||
promise.valueOf = deprecate(function () {
|
promise.valueOf = function () {
|
||||||
var inspected = inspect();
|
var inspected = inspect();
|
||||||
if (inspected.state === "pending" ||
|
if (inspected.state === "pending" ||
|
||||||
inspected.state === "rejected") {
|
inspected.state === "rejected") {
|
||||||
return promise;
|
return promise;
|
||||||
}
|
}
|
||||||
return inspected.value;
|
return inspected.value;
|
||||||
});
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return promise;
|
return promise;
|
||||||
@ -817,7 +853,7 @@ Promise.prototype.then = function (fulfilled, rejected, progressed) {
|
|||||||
return typeof progressed === "function" ? progressed(value) : value;
|
return typeof progressed === "function" ? progressed(value) : value;
|
||||||
}
|
}
|
||||||
|
|
||||||
nextTick(function () {
|
Q.nextTick(function () {
|
||||||
self.promiseDispatch(function (value) {
|
self.promiseDispatch(function (value) {
|
||||||
if (done) {
|
if (done) {
|
||||||
return;
|
return;
|
||||||
@ -858,6 +894,30 @@ Promise.prototype.then = function (fulfilled, rejected, progressed) {
|
|||||||
return deferred.promise;
|
return deferred.promise;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Q.tap = function (promise, callback) {
|
||||||
|
return Q(promise).tap(callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Works almost like "finally", but not called for rejections.
|
||||||
|
* Original resolution value is passed through callback unaffected.
|
||||||
|
* Callback may return a promise that will be awaited for.
|
||||||
|
* @param {Function} callback
|
||||||
|
* @returns {Q.Promise}
|
||||||
|
* @example
|
||||||
|
* doSomething()
|
||||||
|
* .then(...)
|
||||||
|
* .tap(console.log)
|
||||||
|
* .then(...);
|
||||||
|
*/
|
||||||
|
Promise.prototype.tap = function (callback) {
|
||||||
|
callback = Q(callback);
|
||||||
|
|
||||||
|
return this.then(function (value) {
|
||||||
|
return callback.fcall(value).thenResolve(value);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers an observer on a promise.
|
* Registers an observer on a promise.
|
||||||
*
|
*
|
||||||
@ -923,9 +983,7 @@ function nearer(value) {
|
|||||||
*/
|
*/
|
||||||
Q.isPromise = isPromise;
|
Q.isPromise = isPromise;
|
||||||
function isPromise(object) {
|
function isPromise(object) {
|
||||||
return isObject(object) &&
|
return object instanceof Promise;
|
||||||
typeof object.promiseDispatch === "function" &&
|
|
||||||
typeof object.inspect === "function";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Q.isPromiseAlike = isPromiseAlike;
|
Q.isPromiseAlike = isPromiseAlike;
|
||||||
@ -979,43 +1037,15 @@ Promise.prototype.isRejected = function () {
|
|||||||
// shimmed environments, this would naturally be a `Set`.
|
// shimmed environments, this would naturally be a `Set`.
|
||||||
var unhandledReasons = [];
|
var unhandledReasons = [];
|
||||||
var unhandledRejections = [];
|
var unhandledRejections = [];
|
||||||
var unhandledReasonsDisplayed = false;
|
var reportedUnhandledRejections = [];
|
||||||
var trackUnhandledRejections = true;
|
var trackUnhandledRejections = true;
|
||||||
function displayUnhandledReasons() {
|
|
||||||
if (
|
|
||||||
!unhandledReasonsDisplayed &&
|
|
||||||
typeof window !== "undefined" &&
|
|
||||||
!window.Touch &&
|
|
||||||
window.console
|
|
||||||
) {
|
|
||||||
console.warn("[Q] Unhandled rejection reasons (should be empty):",
|
|
||||||
unhandledReasons);
|
|
||||||
}
|
|
||||||
|
|
||||||
unhandledReasonsDisplayed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function logUnhandledReasons() {
|
|
||||||
for (var i = 0; i < unhandledReasons.length; i++) {
|
|
||||||
var reason = unhandledReasons[i];
|
|
||||||
console.warn("Unhandled rejection reason:", reason);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function resetUnhandledRejections() {
|
function resetUnhandledRejections() {
|
||||||
unhandledReasons.length = 0;
|
unhandledReasons.length = 0;
|
||||||
unhandledRejections.length = 0;
|
unhandledRejections.length = 0;
|
||||||
unhandledReasonsDisplayed = false;
|
|
||||||
|
|
||||||
if (!trackUnhandledRejections) {
|
if (!trackUnhandledRejections) {
|
||||||
trackUnhandledRejections = true;
|
trackUnhandledRejections = true;
|
||||||
|
|
||||||
// Show unhandled rejection reasons if Node exits without handling an
|
|
||||||
// outstanding rejection. (Note that Browserify presently produces a
|
|
||||||
// `process` global without the `EventEmitter` `on` method.)
|
|
||||||
if (typeof process !== "undefined" && process.on) {
|
|
||||||
process.on("exit", logUnhandledReasons);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1023,6 +1053,14 @@ function trackRejection(promise, reason) {
|
|||||||
if (!trackUnhandledRejections) {
|
if (!trackUnhandledRejections) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (typeof process === "object" && typeof process.emit === "function") {
|
||||||
|
Q.nextTick.runAfter(function () {
|
||||||
|
if (array_indexOf(unhandledRejections, promise) !== -1) {
|
||||||
|
process.emit("unhandledRejection", reason, promise);
|
||||||
|
reportedUnhandledRejections.push(promise);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
unhandledRejections.push(promise);
|
unhandledRejections.push(promise);
|
||||||
if (reason && typeof reason.stack !== "undefined") {
|
if (reason && typeof reason.stack !== "undefined") {
|
||||||
@ -1030,7 +1068,6 @@ function trackRejection(promise, reason) {
|
|||||||
} else {
|
} else {
|
||||||
unhandledReasons.push("(no stack) " + reason);
|
unhandledReasons.push("(no stack) " + reason);
|
||||||
}
|
}
|
||||||
displayUnhandledReasons();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function untrackRejection(promise) {
|
function untrackRejection(promise) {
|
||||||
@ -1040,6 +1077,15 @@ function untrackRejection(promise) {
|
|||||||
|
|
||||||
var at = array_indexOf(unhandledRejections, promise);
|
var at = array_indexOf(unhandledRejections, promise);
|
||||||
if (at !== -1) {
|
if (at !== -1) {
|
||||||
|
if (typeof process === "object" && typeof process.emit === "function") {
|
||||||
|
Q.nextTick.runAfter(function () {
|
||||||
|
var atReport = array_indexOf(reportedUnhandledRejections, promise);
|
||||||
|
if (atReport !== -1) {
|
||||||
|
process.emit("rejectionHandled", unhandledReasons[at], promise);
|
||||||
|
reportedUnhandledRejections.splice(atReport, 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
unhandledRejections.splice(at, 1);
|
unhandledRejections.splice(at, 1);
|
||||||
unhandledReasons.splice(at, 1);
|
unhandledReasons.splice(at, 1);
|
||||||
}
|
}
|
||||||
@ -1054,9 +1100,6 @@ Q.getUnhandledReasons = function () {
|
|||||||
|
|
||||||
Q.stopUnhandledRejectionTracking = function () {
|
Q.stopUnhandledRejectionTracking = function () {
|
||||||
resetUnhandledRejections();
|
resetUnhandledRejections();
|
||||||
if (typeof process !== "undefined" && process.on) {
|
|
||||||
process.removeListener("exit", logUnhandledReasons);
|
|
||||||
}
|
|
||||||
trackUnhandledRejections = false;
|
trackUnhandledRejections = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1136,7 +1179,7 @@ function fulfill(value) {
|
|||||||
*/
|
*/
|
||||||
function coerce(promise) {
|
function coerce(promise) {
|
||||||
var deferred = defer();
|
var deferred = defer();
|
||||||
nextTick(function () {
|
Q.nextTick(function () {
|
||||||
try {
|
try {
|
||||||
promise.then(deferred.resolve, deferred.reject, deferred.notify);
|
promise.then(deferred.resolve, deferred.reject, deferred.notify);
|
||||||
} catch (exception) {
|
} catch (exception) {
|
||||||
@ -1220,24 +1263,35 @@ function async(makeGenerator) {
|
|||||||
// when verb is "throw", arg is an exception
|
// when verb is "throw", arg is an exception
|
||||||
function continuer(verb, arg) {
|
function continuer(verb, arg) {
|
||||||
var result;
|
var result;
|
||||||
if (hasES6Generators) {
|
|
||||||
|
// Until V8 3.19 / Chromium 29 is released, SpiderMonkey is the only
|
||||||
|
// engine that has a deployed base of browsers that support generators.
|
||||||
|
// However, SM's generators use the Python-inspired semantics of
|
||||||
|
// outdated ES6 drafts. We would like to support ES6, but we'd also
|
||||||
|
// like to make it possible to use generators in deployed browsers, so
|
||||||
|
// we also support Python-style generators. At some point we can remove
|
||||||
|
// this block.
|
||||||
|
|
||||||
|
if (typeof StopIteration === "undefined") {
|
||||||
|
// ES6 Generators
|
||||||
try {
|
try {
|
||||||
result = generator[verb](arg);
|
result = generator[verb](arg);
|
||||||
} catch (exception) {
|
} catch (exception) {
|
||||||
return reject(exception);
|
return reject(exception);
|
||||||
}
|
}
|
||||||
if (result.done) {
|
if (result.done) {
|
||||||
return result.value;
|
return Q(result.value);
|
||||||
} else {
|
} else {
|
||||||
return when(result.value, callback, errback);
|
return when(result.value, callback, errback);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// SpiderMonkey Generators
|
||||||
// FIXME: Remove this case when SM does ES6 generators.
|
// FIXME: Remove this case when SM does ES6 generators.
|
||||||
try {
|
try {
|
||||||
result = generator[verb](arg);
|
result = generator[verb](arg);
|
||||||
} catch (exception) {
|
} catch (exception) {
|
||||||
if (isStopIteration(exception)) {
|
if (isStopIteration(exception)) {
|
||||||
return exception.value;
|
return Q(exception.value);
|
||||||
} else {
|
} else {
|
||||||
return reject(exception);
|
return reject(exception);
|
||||||
}
|
}
|
||||||
@ -1333,7 +1387,7 @@ function dispatch(object, op, args) {
|
|||||||
Promise.prototype.dispatch = function (op, args) {
|
Promise.prototype.dispatch = function (op, args) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var deferred = defer();
|
var deferred = defer();
|
||||||
nextTick(function () {
|
Q.nextTick(function () {
|
||||||
self.promiseDispatch(deferred.resolve, op, args);
|
self.promiseDispatch(deferred.resolve, op, args);
|
||||||
});
|
});
|
||||||
return deferred.promise;
|
return deferred.promise;
|
||||||
@ -1506,7 +1560,7 @@ Promise.prototype.keys = function () {
|
|||||||
Q.all = all;
|
Q.all = all;
|
||||||
function all(promises) {
|
function all(promises) {
|
||||||
return when(promises, function (promises) {
|
return when(promises, function (promises) {
|
||||||
var countDown = 0;
|
var pendingCount = 0;
|
||||||
var deferred = defer();
|
var deferred = defer();
|
||||||
array_reduce(promises, function (undefined, promise, index) {
|
array_reduce(promises, function (undefined, promise, index) {
|
||||||
var snapshot;
|
var snapshot;
|
||||||
@ -1516,12 +1570,12 @@ function all(promises) {
|
|||||||
) {
|
) {
|
||||||
promises[index] = snapshot.value;
|
promises[index] = snapshot.value;
|
||||||
} else {
|
} else {
|
||||||
++countDown;
|
++pendingCount;
|
||||||
when(
|
when(
|
||||||
promise,
|
promise,
|
||||||
function (value) {
|
function (value) {
|
||||||
promises[index] = value;
|
promises[index] = value;
|
||||||
if (--countDown === 0) {
|
if (--pendingCount === 0) {
|
||||||
deferred.resolve(promises);
|
deferred.resolve(promises);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -1532,7 +1586,7 @@ function all(promises) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}, void 0);
|
}, void 0);
|
||||||
if (countDown === 0) {
|
if (pendingCount === 0) {
|
||||||
deferred.resolve(promises);
|
deferred.resolve(promises);
|
||||||
}
|
}
|
||||||
return deferred.promise;
|
return deferred.promise;
|
||||||
@ -1543,6 +1597,55 @@ Promise.prototype.all = function () {
|
|||||||
return all(this);
|
return all(this);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the first resolved promise of an array. Prior rejected promises are
|
||||||
|
* ignored. Rejects only if all promises are rejected.
|
||||||
|
* @param {Array*} an array containing values or promises for values
|
||||||
|
* @returns a promise fulfilled with the value of the first resolved promise,
|
||||||
|
* or a rejected promise if all promises are rejected.
|
||||||
|
*/
|
||||||
|
Q.any = any;
|
||||||
|
|
||||||
|
function any(promises) {
|
||||||
|
if (promises.length === 0) {
|
||||||
|
return Q.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
var deferred = Q.defer();
|
||||||
|
var pendingCount = 0;
|
||||||
|
array_reduce(promises, function (prev, current, index) {
|
||||||
|
var promise = promises[index];
|
||||||
|
|
||||||
|
pendingCount++;
|
||||||
|
|
||||||
|
when(promise, onFulfilled, onRejected, onProgress);
|
||||||
|
function onFulfilled(result) {
|
||||||
|
deferred.resolve(result);
|
||||||
|
}
|
||||||
|
function onRejected() {
|
||||||
|
pendingCount--;
|
||||||
|
if (pendingCount === 0) {
|
||||||
|
deferred.reject(new Error(
|
||||||
|
"Can't get fulfillment value from any promise, all " +
|
||||||
|
"promises were rejected."
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function onProgress(progress) {
|
||||||
|
deferred.notify({
|
||||||
|
index: index,
|
||||||
|
value: progress
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, undefined);
|
||||||
|
|
||||||
|
return deferred.promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
Promise.prototype.any = function () {
|
||||||
|
return any(this);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Waits for all promises to be settled, either fulfilled or
|
* Waits for all promises to be settled, either fulfilled or
|
||||||
* rejected. This is distinct from `all` since that would stop
|
* rejected. This is distinct from `all` since that would stop
|
||||||
@ -1676,7 +1779,7 @@ Promise.prototype.done = function (fulfilled, rejected, progress) {
|
|||||||
var onUnhandledError = function (error) {
|
var onUnhandledError = function (error) {
|
||||||
// forward to a future turn so that ``when``
|
// forward to a future turn so that ``when``
|
||||||
// does not catch it and turn it into a rejection.
|
// does not catch it and turn it into a rejection.
|
||||||
nextTick(function () {
|
Q.nextTick(function () {
|
||||||
makeStackTraceLong(error, promise);
|
makeStackTraceLong(error, promise);
|
||||||
if (Q.onerror) {
|
if (Q.onerror) {
|
||||||
Q.onerror(error);
|
Q.onerror(error);
|
||||||
@ -1703,18 +1806,22 @@ Promise.prototype.done = function (fulfilled, rejected, progress) {
|
|||||||
* some milliseconds time out.
|
* some milliseconds time out.
|
||||||
* @param {Any*} promise
|
* @param {Any*} promise
|
||||||
* @param {Number} milliseconds timeout
|
* @param {Number} milliseconds timeout
|
||||||
* @param {String} custom error message (optional)
|
* @param {Any*} custom error message or Error object (optional)
|
||||||
* @returns a promise for the resolution of the given promise if it is
|
* @returns a promise for the resolution of the given promise if it is
|
||||||
* fulfilled before the timeout, otherwise rejected.
|
* fulfilled before the timeout, otherwise rejected.
|
||||||
*/
|
*/
|
||||||
Q.timeout = function (object, ms, message) {
|
Q.timeout = function (object, ms, error) {
|
||||||
return Q(object).timeout(ms, message);
|
return Q(object).timeout(ms, error);
|
||||||
};
|
};
|
||||||
|
|
||||||
Promise.prototype.timeout = function (ms, message) {
|
Promise.prototype.timeout = function (ms, error) {
|
||||||
var deferred = defer();
|
var deferred = defer();
|
||||||
var timeoutId = setTimeout(function () {
|
var timeoutId = setTimeout(function () {
|
||||||
deferred.reject(new Error(message || "Timed out after " + ms + " ms"));
|
if (!error || "string" === typeof error) {
|
||||||
|
error = new Error(error || "Timed out after " + ms + " ms");
|
||||||
|
error.code = "ETIMEDOUT";
|
||||||
|
}
|
||||||
|
deferred.reject(error);
|
||||||
}, ms);
|
}, ms);
|
||||||
|
|
||||||
this.then(function (value) {
|
this.then(function (value) {
|
||||||
@ -1916,11 +2023,11 @@ function nodeify(object, nodeback) {
|
|||||||
Promise.prototype.nodeify = function (nodeback) {
|
Promise.prototype.nodeify = function (nodeback) {
|
||||||
if (nodeback) {
|
if (nodeback) {
|
||||||
this.then(function (value) {
|
this.then(function (value) {
|
||||||
nextTick(function () {
|
Q.nextTick(function () {
|
||||||
nodeback(null, value);
|
nodeback(null, value);
|
||||||
});
|
});
|
||||||
}, function (error) {
|
}, function (error) {
|
||||||
nextTick(function () {
|
Q.nextTick(function () {
|
||||||
nodeback(error);
|
nodeback(error);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -1929,6 +2036,10 @@ Promise.prototype.nodeify = function (nodeback) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Q.noConflict = function() {
|
||||||
|
throw new Error("Q.noConflict only works when Q is used as a global");
|
||||||
|
};
|
||||||
|
|
||||||
// All code before this point will be filtered from stack traces.
|
// All code before this point will be filtered from stack traces.
|
||||||
var qEndingLine = captureLine();
|
var qEndingLine = captureLine();
|
||||||
|
|
0
bin/node_modules/q/queue.js → node_modules/q/queue.js
generated
vendored
0
bin/node_modules/q/queue.js → node_modules/q/queue.js
generated
vendored
0
bin/node_modules/shelljs/.documentup.json → node_modules/shelljs/.documentup.json
generated
vendored
0
bin/node_modules/shelljs/.documentup.json → node_modules/shelljs/.documentup.json
generated
vendored
0
bin/node_modules/shelljs/.jshintrc → node_modules/shelljs/.jshintrc
generated
vendored
0
bin/node_modules/shelljs/.jshintrc → node_modules/shelljs/.jshintrc
generated
vendored
0
bin/node_modules/shelljs/.npmignore → node_modules/shelljs/.npmignore
generated
vendored
0
bin/node_modules/shelljs/.npmignore → node_modules/shelljs/.npmignore
generated
vendored
3
bin/node_modules/shelljs/.travis.yml → node_modules/shelljs/.travis.yml
generated
vendored
3
bin/node_modules/shelljs/.travis.yml → node_modules/shelljs/.travis.yml
generated
vendored
@ -1,5 +1,6 @@
|
|||||||
language: node_js
|
language: node_js
|
||||||
node_js:
|
node_js:
|
||||||
- "0.8"
|
|
||||||
- "0.10"
|
- "0.10"
|
||||||
- "0.11"
|
- "0.11"
|
||||||
|
- "0.12"
|
||||||
|
|
0
bin/node_modules/shelljs/LICENSE → node_modules/shelljs/LICENSE
generated
vendored
0
bin/node_modules/shelljs/LICENSE → node_modules/shelljs/LICENSE
generated
vendored
53
bin/node_modules/shelljs/README.md → node_modules/shelljs/README.md
generated
vendored
53
bin/node_modules/shelljs/README.md → node_modules/shelljs/README.md
generated
vendored
@ -13,6 +13,8 @@ The project is [unit-tested](http://travis-ci.org/arturadib/shelljs) and battled
|
|||||||
|
|
||||||
and [many more](https://npmjs.org/browse/depended/shelljs).
|
and [many more](https://npmjs.org/browse/depended/shelljs).
|
||||||
|
|
||||||
|
Connect with [@r2r](http://twitter.com/r2r) on Twitter for questions, suggestions, etc.
|
||||||
|
|
||||||
## Installing
|
## Installing
|
||||||
|
|
||||||
Via npm:
|
Via npm:
|
||||||
@ -130,15 +132,21 @@ target.docs = ->
|
|||||||
text.to 'docs/my_docs.md'
|
text.to 'docs/my_docs.md'
|
||||||
```
|
```
|
||||||
|
|
||||||
To run the target `all`, call the above script without arguments: `$ node make`. To run the target `docs`: `$ node make docs`, and so on.
|
To run the target `all`, call the above script without arguments: `$ node make`. To run the target `docs`: `$ node make docs`.
|
||||||
|
|
||||||
|
You can also pass arguments to your targets by using the `--` separator. For example, to pass `arg1` and `arg2` to a target `bundle`, do `$ node make bundle -- arg1 arg2`:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
require('shelljs/make');
|
||||||
|
|
||||||
|
target.bundle = function(argsArray) {
|
||||||
|
// argsArray = ['arg1', 'arg2']
|
||||||
|
/* ... */
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
<!-- DO NOT MODIFY BEYOND THIS POINT - IT'S AUTOMATICALLY GENERATED -->
|
||||||
<!--
|
|
||||||
|
|
||||||
DO NOT MODIFY BEYOND THIS POINT - IT'S AUTOMATICALLY GENERATED
|
|
||||||
|
|
||||||
-->
|
|
||||||
|
|
||||||
|
|
||||||
## Command reference
|
## Command reference
|
||||||
@ -266,7 +274,7 @@ Available expression primaries:
|
|||||||
+ `'-d', 'path'`: true if path is a directory
|
+ `'-d', 'path'`: true if path is a directory
|
||||||
+ `'-e', 'path'`: true if path exists
|
+ `'-e', 'path'`: true if path exists
|
||||||
+ `'-f', 'path'`: true if path is a regular file
|
+ `'-f', 'path'`: true if path is a regular file
|
||||||
+ `'-L', 'path'`: true if path is a symboilc link
|
+ `'-L', 'path'`: true if path is a symbolic link
|
||||||
+ `'-p', 'path'`: true if path is a pipe (FIFO)
|
+ `'-p', 'path'`: true if path is a pipe (FIFO)
|
||||||
+ `'-S', 'path'`: true if path is a socket
|
+ `'-S', 'path'`: true if path is a socket
|
||||||
|
|
||||||
@ -320,7 +328,7 @@ Analogous to the redirect-and-append operator `>>` in Unix, but works with JavaS
|
|||||||
those returned by `cat`, `grep`, etc).
|
those returned by `cat`, `grep`, etc).
|
||||||
|
|
||||||
|
|
||||||
### sed([options ,] search_regex, replace_str, file)
|
### sed([options ,] search_regex, replacement, file)
|
||||||
Available options:
|
Available options:
|
||||||
|
|
||||||
+ `-i`: Replace contents of 'file' in-place. _Note that no backups will be created!_
|
+ `-i`: Replace contents of 'file' in-place. _Note that no backups will be created!_
|
||||||
@ -333,7 +341,7 @@ sed(/.*DELETE_THIS_LINE.*\n/, '', 'source.js');
|
|||||||
```
|
```
|
||||||
|
|
||||||
Reads an input string from `file` and performs a JavaScript `replace()` on the input
|
Reads an input string from `file` and performs a JavaScript `replace()` on the input
|
||||||
using the given search regex and replacement string. Returns the new string after replacement.
|
using the given search regex and replacement string or function. Returns the new string after replacement.
|
||||||
|
|
||||||
|
|
||||||
### grep([options ,] regex_filter, file [, file ...])
|
### grep([options ,] regex_filter, file [, file ...])
|
||||||
@ -439,6 +447,23 @@ Display the list of currently remembered directories. Returns an array of paths
|
|||||||
See also: pushd, popd
|
See also: pushd, popd
|
||||||
|
|
||||||
|
|
||||||
|
### ln(options, source, dest)
|
||||||
|
### ln(source, dest)
|
||||||
|
Available options:
|
||||||
|
|
||||||
|
+ `s`: symlink
|
||||||
|
+ `f`: force
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
ln('file', 'newlink');
|
||||||
|
ln('-sf', 'file', 'existing');
|
||||||
|
```
|
||||||
|
|
||||||
|
Links source to dest. Use -f to force the link, should dest already exist.
|
||||||
|
|
||||||
|
|
||||||
### exit(code)
|
### exit(code)
|
||||||
Exits the current process with the given exit code.
|
Exits the current process with the given exit code.
|
||||||
|
|
||||||
@ -531,10 +556,11 @@ otherwise returns string explaining the error
|
|||||||
Example:
|
Example:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var silentState = config.silent; // save old silent state
|
var sh = require('shelljs');
|
||||||
config.silent = true;
|
var silentState = sh.config.silent; // save old silent state
|
||||||
|
sh.config.silent = true;
|
||||||
/* ... */
|
/* ... */
|
||||||
config.silent = silentState; // restore old silent state
|
sh.config.silent = silentState; // restore old silent state
|
||||||
```
|
```
|
||||||
|
|
||||||
Suppresses all command output if `true`, except for `echo()` calls.
|
Suppresses all command output if `true`, except for `echo()` calls.
|
||||||
@ -544,6 +570,7 @@ Default is `false`.
|
|||||||
Example:
|
Example:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
|
require('shelljs/global');
|
||||||
config.fatal = true;
|
config.fatal = true;
|
||||||
cp('this_file_does_not_exist', '/dev/null'); // dies here
|
cp('this_file_does_not_exist', '/dev/null'); // dies here
|
||||||
/* more commands... */
|
/* more commands... */
|
9
node_modules/shelljs/RELEASE.md
generated
vendored
Normal file
9
node_modules/shelljs/RELEASE.md
generated
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# Release steps
|
||||||
|
|
||||||
|
* Ensure master passes CI tests
|
||||||
|
* Bump version in package.json. Any breaking change or new feature should bump minor (or even major). Non-breaking changes or fixes can just bump patch.
|
||||||
|
* Update README manually if the changes are not documented in-code. If so, run `scripts/generate-docs.js`
|
||||||
|
* Commit
|
||||||
|
* `$ git tag <version>` (see `git tag -l` for latest)
|
||||||
|
* `$ git push origin master --tags`
|
||||||
|
* `$ npm publish .`
|
0
bin/node_modules/shelljs/bin/shjs → node_modules/shelljs/bin/shjs
generated
vendored
Executable file → Normal file
0
bin/node_modules/shelljs/bin/shjs → node_modules/shelljs/bin/shjs
generated
vendored
Executable file → Normal file
0
bin/node_modules/shelljs/global.js → node_modules/shelljs/global.js
generated
vendored
0
bin/node_modules/shelljs/global.js → node_modules/shelljs/global.js
generated
vendored
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user