diff options
Diffstat (limited to 'StoneIsland/platforms/ios/cordova/lib')
16 files changed, 787 insertions, 729 deletions
diff --git a/StoneIsland/platforms/ios/cordova/lib/Podfile.js b/StoneIsland/platforms/ios/cordova/lib/Podfile.js index 084c10c3..49173c4c 100755 --- a/StoneIsland/platforms/ios/cordova/lib/Podfile.js +++ b/StoneIsland/platforms/ios/cordova/lib/Podfile.js @@ -16,18 +16,19 @@ specific language governing permissions and limitations under the License. */ +'use strict'; -var fs = require('fs'), - path = require('path'), - util = require('util'), - events = require('cordova-common').events, - Q = require('q'), - superspawn = require('cordova-common').superspawn, - CordovaError = require('cordova-common').CordovaError; +var fs = require('fs'); +var path = require('path'); +var util = require('util'); +var events = require('cordova-common').events; +var Q = require('q'); +var superspawn = require('cordova-common').superspawn; +var CordovaError = require('cordova-common').CordovaError; Podfile.FILENAME = 'Podfile'; -function Podfile(podFilePath, projectName) { +function Podfile (podFilePath, projectName) { this.podToken = '##INSERT_POD##'; this.path = podFilePath; @@ -53,12 +54,12 @@ function Podfile(podFilePath, projectName) { this.write(); } else { events.emit('verbose', 'Podfile found in platforms/ios'); - // parse for pods + // parse for pods this.pods = this.__parseForPods(fs.readFileSync(this.path, 'utf8')); } } -Podfile.prototype.__parseForPods = function(text) { +Podfile.prototype.__parseForPods = function (text) { // split by \n var arr = text.split('\n'); @@ -69,38 +70,45 @@ Podfile.prototype.__parseForPods = function(text) { var podRE = new RegExp('pod \'([^\']*)\'\\s*,?\\s*(.*)'); // only grab lines that don't have the pod spec' - return arr.filter(function(line) { + return arr.filter(function (line) { var m = podRE.exec(line); return (m !== null); }) - .reduce(function(obj, line){ - var m = podRE.exec(line); + .reduce(function (obj, line) { + var m = podRE.exec(line); - if (m !== null) { - // strip out any single quotes around the value m[2] - var podSpec = m[2].replace(/^\'|\'$/g, ''); - obj[m[1]] = podSpec; // i.e pod 'Foo', '1.2' ==> { 'Foo' : '1.2'} - } + if (m !== null) { + // strip out any single quotes around the value m[2] + var podSpec = m[2].replace(/^\'|\'$/g, ''); /* eslint no-useless-escape : 0 */ + obj[m[1]] = podSpec; // i.e pod 'Foo', '1.2' ==> { 'Foo' : '1.2'} + } - return obj; - }, {}); + return obj; + }, {}); }; -Podfile.prototype.getTemplate = function() { +Podfile.prototype.escapeSingleQuotes = function (string) { + return string.replace('\'', '\\\''); +}; + +Podfile.prototype.getTemplate = function () { + // Escaping possible ' in the project name + var projectName = this.escapeSingleQuotes(this.projectName); return util.format( - '# DO NOT MODIFY -- auto-generated by Apache Cordova\n' + + '# DO NOT MODIFY -- auto-generated by Apache Cordova\n' + 'platform :ios, \'8.0\'\n' + 'target \'%s\' do\n' + '\tproject \'%s.xcodeproj\'\n' + '%s\n' + 'end\n', - this.projectName, this.projectName, this.podToken); + projectName, projectName, this.podToken); }; -Podfile.prototype.addSpec = function(name, spec) { +Podfile.prototype.addSpec = function (name, spec) { name = name || ''; - spec = spec; // optional + // optional + spec = spec; /* eslint no-self-assign : 0 */ if (!name.length) { // blank names are not allowed throw new CordovaError('Podfile addSpec: name is not specified.'); @@ -112,39 +120,39 @@ Podfile.prototype.addSpec = function(name, spec) { events.emit('verbose', util.format('Added pod line for `%s`', name)); }; -Podfile.prototype.removeSpec = function(name) { +Podfile.prototype.removeSpec = function (name) { if (this.existsSpec(name)) { delete this.pods[name]; this.__dirty = true; } - + events.emit('verbose', util.format('Removed pod line for `%s`', name)); }; -Podfile.prototype.getSpec = function(name) { +Podfile.prototype.getSpec = function (name) { return this.pods[name]; }; -Podfile.prototype.existsSpec = function(name) { +Podfile.prototype.existsSpec = function (name) { return (name in this.pods); }; -Podfile.prototype.clear = function() { +Podfile.prototype.clear = function () { this.pods = {}; this.__dirty = true; }; -Podfile.prototype.destroy = function() { +Podfile.prototype.destroy = function () { fs.unlinkSync(this.path); events.emit('verbose', util.format('Deleted `%s`', this.path)); }; -Podfile.prototype.write = function() { +Podfile.prototype.write = function () { var text = this.getTemplate(); var self = this; var podsString = - Object.keys(this.pods).map(function(key) { + Object.keys(this.pods).map(function (key) { var name = key; var spec = self.pods[key]; @@ -159,8 +167,7 @@ Podfile.prototype.write = function() { } else { return util.format('\tpod \'%s\'', name); } - }) - .join('\n'); + }).join('\n'); text = text.replace(this.podToken, podsString); fs.writeFileSync(this.path, text, 'utf8'); @@ -169,14 +176,16 @@ Podfile.prototype.write = function() { events.emit('verbose', 'Wrote to Podfile.'); }; -Podfile.prototype.isDirty = function() { +Podfile.prototype.isDirty = function () { return this.__dirty; }; -Podfile.prototype.before_install = function() { +Podfile.prototype.before_install = function (toolOptions) { + toolOptions = toolOptions || {}; + // Template tokens in order: project name, project name, debug | release var template = - '// DO NOT MODIFY -- auto-generated by Apache Cordova\n' + + '// DO NOT MODIFY -- auto-generated by Apache Cordova\n' + '#include "Pods/Target Support Files/Pods-%s/Pods-%s.%s.xcconfig"'; var debugContents = util.format(template, this.projectName, this.projectName, 'debug'); @@ -188,10 +197,10 @@ Podfile.prototype.before_install = function() { fs.writeFileSync(debugConfigPath, debugContents, 'utf8'); fs.writeFileSync(releaseConfigPath, releaseContents, 'utf8'); - return Q.resolve(); + return Q.resolve(toolOptions); }; -Podfile.prototype.install = function(requirementsCheckerFunction) { +Podfile.prototype.install = function (requirementsCheckerFunction) { var opts = {}; opts.cwd = path.join(this.path, '..'); // parent path of this Podfile opts.stdio = 'pipe'; @@ -203,28 +212,34 @@ Podfile.prototype.install = function(requirementsCheckerFunction) { } return requirementsCheckerFunction() - .then(function() { - return self.before_install(); - }) - .then(function() { - return superspawn.spawn('pod', ['install', '--verbose'], opts) - .progress(function (stdio){ - if (stdio.stderr) { console.error(stdio.stderr); } - if (stdio.stdout) { - if (first) { - events.emit('verbose', '==== pod install start ====\n'); - first = false; - } - events.emit('verbose', stdio.stdout); - } + .then(function (toolOptions) { + return self.before_install(toolOptions); + }) + .then(function (toolOptions) { + if (toolOptions.ignore) { + events.emit('verbose', '==== pod install start ====\n'); + events.emit('verbose', toolOptions.ignoreMessage); + return Q.resolve(); + } else { + return superspawn.spawn('pod', ['install', '--verbose'], opts) + .progress(function (stdio) { + if (stdio.stderr) { console.error(stdio.stderr); } + if (stdio.stdout) { + if (first) { + events.emit('verbose', '==== pod install start ====\n'); + first = false; + } + events.emit('verbose', stdio.stdout); + } + }); + } + }) + .then(function () { // done + events.emit('verbose', '==== pod install end ====\n'); + }) + .fail(function (error) { + throw error; }); - }) - .then(function() { // done - events.emit('verbose', '==== pod install end ====\n'); - }) - .fail(function(error){ - throw error; - }); }; -module.exports.Podfile = Podfile;
\ No newline at end of file +module.exports.Podfile = Podfile; diff --git a/StoneIsland/platforms/ios/cordova/lib/PodsJson.js b/StoneIsland/platforms/ios/cordova/lib/PodsJson.js index b13a1afe..04705273 100755 --- a/StoneIsland/platforms/ios/cordova/lib/PodsJson.js +++ b/StoneIsland/platforms/ios/cordova/lib/PodsJson.js @@ -17,15 +17,15 @@ under the License. */ -var fs = require('fs'), - path = require('path'), - util = require('util'), - events = require('cordova-common').events, - CordovaError = require('cordova-common').CordovaError; +var fs = require('fs'); +var path = require('path'); +var util = require('util'); +var events = require('cordova-common').events; +var CordovaError = require('cordova-common').CordovaError; PodsJson.FILENAME = 'pods.json'; -function PodsJson(podsJsonPath) { +function PodsJson (podsJsonPath) { this.path = podsJsonPath; this.contents = null; this.__dirty = false; @@ -41,18 +41,18 @@ function PodsJson(podsJsonPath) { this.clear(); this.write(); } else { - events.emit('verbose', 'pods.json found in platforms/ios'); + events.emit('verbose', 'pods.json found in platforms/ios'); // load contents this.contents = fs.readFileSync(this.path, 'utf8'); this.contents = JSON.parse(this.contents); } } -PodsJson.prototype.get = function(name) { +PodsJson.prototype.get = function (name) { return this.contents[name]; }; -PodsJson.prototype.remove = function(name) { +PodsJson.prototype.remove = function (name) { if (this.contents[name]) { delete this.contents[name]; this.__dirty = true; @@ -60,17 +60,17 @@ PodsJson.prototype.remove = function(name) { } }; -PodsJson.prototype.clear = function() { +PodsJson.prototype.clear = function () { this.contents = {}; this.__dirty = true; }; -PodsJson.prototype.destroy = function() { +PodsJson.prototype.destroy = function () { fs.unlinkSync(this.path); events.emit('verbose', util.format('Deleted `%s`', this.path)); }; -PodsJson.prototype.write = function() { +PodsJson.prototype.write = function () { if (this.contents) { fs.writeFileSync(this.path, JSON.stringify(this.contents, null, 4)); this.__dirty = false; @@ -78,11 +78,11 @@ PodsJson.prototype.write = function() { } }; -PodsJson.prototype.set = function(name, type, spec, count) { +PodsJson.prototype.set = function (name, type, spec, count) { this.setJson(name, { name: name, type: type, spec: spec, count: count }); }; -PodsJson.prototype.increment = function(name) { +PodsJson.prototype.increment = function (name) { var val = this.get(name); if (val) { val.count++; @@ -90,7 +90,7 @@ PodsJson.prototype.increment = function(name) { } }; -PodsJson.prototype.decrement = function(name) { +PodsJson.prototype.decrement = function (name) { var val = this.get(name); if (val) { val.count--; @@ -102,13 +102,13 @@ PodsJson.prototype.decrement = function(name) { } }; -PodsJson.prototype.setJson = function(name, json) { +PodsJson.prototype.setJson = function (name, json) { this.contents[name] = json; this.__dirty = true; events.emit('verbose', util.format('Set pods.json for `%s`', name)); }; -PodsJson.prototype.isDirty = function() { +PodsJson.prototype.isDirty = function () { return this.__dirty; }; diff --git a/StoneIsland/platforms/ios/cordova/lib/build.js b/StoneIsland/platforms/ios/cordova/lib/build.js index 29d808ab..f51b084c 100755 --- a/StoneIsland/platforms/ios/cordova/lib/build.js +++ b/StoneIsland/platforms/ios/cordova/lib/build.js @@ -17,23 +17,16 @@ * under the License. */ -/*jshint node: true*/ +var Q = require('q'); +var path = require('path'); +var shell = require('shelljs'); +var spawn = require('./spawn'); +var fs = require('fs'); +var plist = require('plist'); +var util = require('util'); -var Q = require('q'), - path = require('path'), - shell = require('shelljs'), - spawn = require('./spawn'), - fs = require('fs'), - plist = require('plist'), - util = require('util'); - -var check_reqs; -try { - check_reqs = require('./check_reqs'); -} catch (err) { - // For unit tests, check_reqs.js is not a sibling to build.js - check_reqs = require('../../../../lib/check_reqs'); -} +var check_reqs = require('./check_reqs'); +var projectFile = require('./projectFile'); var events = require('cordova-common').events; @@ -41,41 +34,43 @@ var projectPath = path.join(__dirname, '..', '..'); var projectName = null; // These are regular expressions to detect if the user is changing any of the built-in xcodebuildArgs +/* eslint-disable no-useless-escape */ var buildFlagMatchers = { - 'xcconfig' : /^\-xcconfig\s*(.*)$/, - 'workspace' : /^\-workspace\s*(.*)/, - 'scheme' : /^\-scheme\s*(.*)/, - 'configuration' : /^\-configuration\s*(.*)/, - 'sdk' : /^\-sdk\s*(.*)/, - 'destination' : /^\-destination\s*(.*)/, - 'archivePath' : /^\-archivePath\s*(.*)/, - 'configuration_build_dir' : /^(CONFIGURATION_BUILD_DIR=.*)/, - 'shared_precomps_dir' : /^(SHARED_PRECOMPS_DIR=.*)/ + 'xcconfig': /^\-xcconfig\s*(.*)$/, + 'workspace': /^\-workspace\s*(.*)/, + 'scheme': /^\-scheme\s*(.*)/, + 'configuration': /^\-configuration\s*(.*)/, + 'sdk': /^\-sdk\s*(.*)/, + 'destination': /^\-destination\s*(.*)/, + 'archivePath': /^\-archivePath\s*(.*)/, + 'configuration_build_dir': /^(CONFIGURATION_BUILD_DIR=.*)/, + 'shared_precomps_dir': /^(SHARED_PRECOMPS_DIR=.*)/ }; +/* eslint-enable no-useless-escape */ /** * Returns a promise that resolves to the default simulator target; the logic here - * matches what `cordova emulate ios` does. - * + * matches what `cordova emulate ios` does. + * * The return object has two properties: `name` (the Xcode destination name), * `identifier` (the simctl identifier), and `simIdentifier` (essentially the cordova emulate target) - * + * * @return {Promise} */ -function getDefaultSimulatorTarget() { +function getDefaultSimulatorTarget () { return require('./list-emulator-build-targets').run() - .then(function (emulators) { - var targetEmulator; - if (emulators.length > 0) { - targetEmulator = emulators[0]; - } - emulators.forEach(function (emulator) { - if (emulator.name.indexOf('iPhone') === 0) { - targetEmulator = emulator; + .then(function (emulators) { + var targetEmulator; + if (emulators.length > 0) { + targetEmulator = emulators[0]; } + emulators.forEach(function (emulator) { + if (emulator.name.indexOf('iPhone') === 0) { + targetEmulator = emulator; + } + }); + return targetEmulator; }); - return targetEmulator; - }); } module.exports.run = function (buildOpts) { @@ -91,126 +86,153 @@ module.exports.run = function (buildOpts) { return Q.reject('Cannot specify "device" and "emulator" options together.'); } - if(buildOpts.buildConfig) { - if(!fs.existsSync(buildOpts.buildConfig)) { + if (buildOpts.buildConfig) { + if (!fs.existsSync(buildOpts.buildConfig)) { return Q.reject('Build config file does not exist:' + buildOpts.buildConfig); } - events.emit('log','Reading build config file:', path.resolve(buildOpts.buildConfig)); + events.emit('log', 'Reading build config file:', path.resolve(buildOpts.buildConfig)); var contents = fs.readFileSync(buildOpts.buildConfig, 'utf-8'); var buildConfig = JSON.parse(contents.replace(/^\ufeff/, '')); // Remove BOM - if(buildConfig.ios) { + if (buildConfig.ios) { var buildType = buildOpts.release ? 'release' : 'debug'; var config = buildConfig.ios[buildType]; - if(config) { - ['codeSignIdentity', 'codeSignResourceRules', 'provisioningProfile', 'developmentTeam', 'packageType', 'buildFlag'].forEach( - function(key) { + if (config) { + ['codeSignIdentity', 'codeSignResourceRules', 'provisioningProfile', 'developmentTeam', 'packageType', 'buildFlag', 'iCloudContainerEnvironment'].forEach( + function (key) { buildOpts[key] = buildOpts[key] || config[key]; }); } } } -return require('./list-devices').run() - .then(function (devices) { - if (devices.length > 0 && !(buildOpts.emulator)) { - // we also explicitly set device flag in options as we pass - // those parameters to other api (build as an example) - buildOpts.device = true; - return check_reqs.check_ios_deploy(); - } - }).then(function () { - // CB-12287: Determine the device we should target when building for a simulator - if (!buildOpts.device) { - var promise; - if (buildOpts.target) { + return require('./list-devices').run() + .then(function (devices) { + if (devices.length > 0 && !(buildOpts.emulator)) { + // we also explicitly set device flag in options as we pass + // those parameters to other api (build as an example) + buildOpts.device = true; + return check_reqs.check_ios_deploy(); + } + }).then(function () { + // CB-12287: Determine the device we should target when building for a simulator + if (!buildOpts.device) { + var newTarget = buildOpts.target || ''; + + if (newTarget) { + // only grab the device name, not the runtime specifier + newTarget = newTarget.split(',')[0]; + } // a target was given to us, find the matching Xcode destination name - promise = require('./list-emulator-build-targets').targetForSimIdentifier(buildOpts.target); - } else { - // no target provided, pick a default one (matching our emulator logic) - promise = getDefaultSimulatorTarget(); + var promise = require('./list-emulator-build-targets').targetForSimIdentifier(newTarget); + return promise.then(function (theTarget) { + if (!theTarget) { + return getDefaultSimulatorTarget().then(function (defaultTarget) { + emulatorTarget = defaultTarget.name; + events.emit('log', 'Building for ' + emulatorTarget + ' Simulator'); + return emulatorTarget; + }); + } else { + emulatorTarget = theTarget.name; + events.emit('log', 'Building for ' + emulatorTarget + ' Simulator'); + return emulatorTarget; + } + }); } - return promise.then(function(theTarget) { - emulatorTarget = theTarget.name; - events.emit('log', 'Building for ' + emulatorTarget + ' Simulator'); - }); - } - }).then(function () { - return check_reqs.run(); - }).then(function () { - return findXCodeProjectIn(projectPath); - }).then(function (name) { - projectName = name; - var extraConfig = ''; - if (buildOpts.codeSignIdentity) { - extraConfig += 'CODE_SIGN_IDENTITY = ' + buildOpts.codeSignIdentity + '\n'; - extraConfig += 'CODE_SIGN_IDENTITY[sdk=iphoneos*] = ' + buildOpts.codeSignIdentity + '\n'; - } - if (buildOpts.codeSignResourceRules) { - extraConfig += 'CODE_SIGN_RESOURCE_RULES_PATH = ' + buildOpts.codeSignResourceRules + '\n'; - } - if (buildOpts.provisioningProfile) { - extraConfig += 'PROVISIONING_PROFILE = ' + buildOpts.provisioningProfile + '\n'; - } - if (buildOpts.developmentTeam) { - extraConfig += 'DEVELOPMENT_TEAM = ' + buildOpts.developmentTeam + '\n'; - } - return Q.nfcall(fs.writeFile, path.join(__dirname, '..', 'build-extras.xcconfig'), extraConfig, 'utf-8'); - }).then(function () { - var configuration = buildOpts.release ? 'Release' : 'Debug'; + }).then(function () { + return check_reqs.run(); + }).then(function () { + return findXCodeProjectIn(projectPath); + }).then(function (name) { + projectName = name; + var extraConfig = ''; + if (buildOpts.codeSignIdentity) { + extraConfig += 'CODE_SIGN_IDENTITY = ' + buildOpts.codeSignIdentity + '\n'; + extraConfig += 'CODE_SIGN_IDENTITY[sdk=iphoneos*] = ' + buildOpts.codeSignIdentity + '\n'; + } + if (buildOpts.codeSignResourceRules) { + extraConfig += 'CODE_SIGN_RESOURCE_RULES_PATH = ' + buildOpts.codeSignResourceRules + '\n'; + } + if (buildOpts.provisioningProfile) { + extraConfig += 'PROVISIONING_PROFILE = ' + buildOpts.provisioningProfile + '\n'; + } + if (buildOpts.developmentTeam) { + extraConfig += 'DEVELOPMENT_TEAM = ' + buildOpts.developmentTeam + '\n'; + } + return Q.nfcall(fs.writeFile, path.join(__dirname, '..', 'build-extras.xcconfig'), extraConfig, 'utf-8'); + }).then(function () { + var configuration = buildOpts.release ? 'Release' : 'Debug'; - events.emit('log','Building project: ' + path.join(projectPath, projectName + '.xcworkspace')); - events.emit('log','\tConfiguration: ' + configuration); - events.emit('log','\tPlatform: ' + (buildOpts.device ? 'device' : 'emulator')); + events.emit('log', 'Building project: ' + path.join(projectPath, projectName + '.xcworkspace')); + events.emit('log', '\tConfiguration: ' + configuration); + events.emit('log', '\tPlatform: ' + (buildOpts.device ? 'device' : 'emulator')); - var buildOutputDir = path.join(projectPath, 'build', (buildOpts.device ? 'device' : 'emulator')); + var buildOutputDir = path.join(projectPath, 'build', (buildOpts.device ? 'device' : 'emulator')); - // remove the build/device folder before building - return spawn('rm', [ '-rf', buildOutputDir ], projectPath) - .then(function() { - var xcodebuildArgs = getXcodeBuildArgs(projectName, projectPath, configuration, buildOpts.device, buildOpts.buildFlag, emulatorTarget); - return spawn('xcodebuild', xcodebuildArgs, projectPath); - }); + // remove the build/device folder before building + return spawn('rm', [ '-rf', buildOutputDir ], projectPath) + .then(function () { + var xcodebuildArgs = getXcodeBuildArgs(projectName, projectPath, configuration, buildOpts.device, buildOpts.buildFlag, emulatorTarget); + return spawn('xcodebuild', xcodebuildArgs, projectPath); + }); - }).then(function () { - if (!buildOpts.device || buildOpts.noSign) { - return; - } + }).then(function () { + if (!buildOpts.device || buildOpts.noSign) { + return; + } - var exportOptions = {'compileBitcode': false, 'method': 'development'}; + var locations = { + root: projectPath, + pbxproj: path.join(projectPath, projectName + '.xcodeproj', 'project.pbxproj') + }; - if (buildOpts.packageType) { - exportOptions.method = buildOpts.packageType; - } + var bundleIdentifier = projectFile.parse(locations).getPackageName(); + var exportOptions = {'compileBitcode': false, 'method': 'development'}; - if (buildOpts.developmentTeam) { - exportOptions.teamID = buildOpts.developmentTeam; - } + if (buildOpts.packageType) { + exportOptions.method = buildOpts.packageType; + } - var exportOptionsPlist = plist.build(exportOptions); - var exportOptionsPath = path.join(projectPath, 'exportOptions.plist'); + if (buildOpts.iCloudContainerEnvironment) { + exportOptions.iCloudContainerEnvironment = buildOpts.iCloudContainerEnvironment; + } - var buildOutputDir = path.join(projectPath, 'build', 'device'); + if (buildOpts.developmentTeam) { + exportOptions.teamID = buildOpts.developmentTeam; + } + if (buildOpts.provisioningProfile && bundleIdentifier) { + exportOptions.provisioningProfiles = { [ bundleIdentifier ]: String(buildOpts.provisioningProfile) }; + exportOptions.signingStyle = 'manual'; + } - function checkSystemRuby() { - var ruby_cmd = shell.which('ruby'); + if (buildOpts.codeSignIdentity) { + exportOptions.signingCertificate = buildOpts.codeSignIdentity; + } - if (ruby_cmd != '/usr/bin/ruby') { - events.emit('warn', 'Non-system Ruby in use. This may cause packaging to fail.\n' + - 'If you use RVM, please run `rvm use system`.\n' + - 'If you use chruby, please run `chruby system`.'); - } - } + var exportOptionsPlist = plist.build(exportOptions); + var exportOptionsPath = path.join(projectPath, 'exportOptions.plist'); - function packageArchive() { - var xcodearchiveArgs = getXcodeArchiveArgs(projectName, projectPath, buildOutputDir, exportOptionsPath); - return spawn('xcodebuild', xcodearchiveArgs, projectPath); - } + var buildOutputDir = path.join(projectPath, 'build', 'device'); + + function checkSystemRuby () { + var ruby_cmd = shell.which('ruby'); + + if (ruby_cmd !== '/usr/bin/ruby') { + events.emit('warn', 'Non-system Ruby in use. This may cause packaging to fail.\n' + + 'If you use RVM, please run `rvm use system`.\n' + + 'If you use chruby, please run `chruby system`.'); + } + } + + function packageArchive () { + var xcodearchiveArgs = getXcodeArchiveArgs(projectName, projectPath, buildOutputDir, exportOptionsPath); + return spawn('xcodebuild', xcodearchiveArgs, projectPath); + } - return Q.nfcall(fs.writeFile, exportOptionsPath, exportOptionsPlist, 'utf-8') + return Q.nfcall(fs.writeFile, exportOptionsPath, exportOptionsPlist, 'utf-8') .then(checkSystemRuby) .then(packageArchive); - }); + }); }; /** @@ -218,7 +240,7 @@ return require('./list-devices').run() * @param {String} projectPath Path where to search project * @return {Promise} Promise either fulfilled with project name or rejected */ -function findXCodeProjectIn(projectPath) { +function findXCodeProjectIn (projectPath) { // 'Searching for Xcode project in ' + projectPath); var xcodeProjFiles = shell.ls(projectPath).filter(function (name) { return path.extname(name) === '.xcodeproj'; @@ -228,7 +250,7 @@ function findXCodeProjectIn(projectPath) { return Q.reject('No Xcode project found in ' + projectPath); } if (xcodeProjFiles.length > 1) { - events.emit('warn','Found multiple .xcodeproj directories in \n' + + events.emit('warn', 'Found multiple .xcodeproj directories in \n' + projectPath + '\nUsing first one'); } @@ -248,7 +270,7 @@ module.exports.findXCodeProjectIn = findXCodeProjectIn; * @param {String} emulatorTarget Target for emulator (rather than default) * @return {Array} Array of arguments that could be passed directly to spawn method */ -function getXcodeBuildArgs(projectName, projectPath, configuration, isDevice, buildFlags, emulatorTarget) { +function getXcodeBuildArgs (projectName, projectPath, configuration, isDevice, buildFlags, emulatorTarget) { var xcodebuildArgs; var options; var buildActions; @@ -260,16 +282,16 @@ function getXcodeBuildArgs(projectName, projectPath, configuration, isDevice, bu if (typeof buildFlags === 'string' || buildFlags instanceof String) { parseBuildFlag(buildFlags, customArgs); } else { // buildFlags is an Array of strings - buildFlags.forEach( function(flag) { + buildFlags.forEach(function (flag) { parseBuildFlag(flag, customArgs); }); } } - + if (isDevice) { options = [ '-xcconfig', customArgs.xcconfig || path.join(__dirname, '..', 'build-' + configuration.toLowerCase() + '.xcconfig'), - '-workspace', customArgs.workspace || projectName + '.xcworkspace', + '-workspace', customArgs.workspace || projectName + '.xcworkspace', '-scheme', customArgs.scheme || projectName, '-configuration', customArgs.configuration || configuration, '-destination', customArgs.destination || 'generic/platform=iOS', @@ -309,7 +331,6 @@ function getXcodeBuildArgs(projectName, projectPath, configuration, isDevice, bu return xcodebuildArgs; } - /** * Returns array of arguments for xcodebuild * @param {String} projectName Name of xcode project @@ -318,16 +339,16 @@ function getXcodeBuildArgs(projectName, projectPath, configuration, isDevice, bu * @param {String} exportOptionsPath Path to the exportOptions.plist file * @return {Array} Array of arguments that could be passed directly to spawn method */ -function getXcodeArchiveArgs(projectName, projectPath, outputPath, exportOptionsPath) { - return [ - '-exportArchive', - '-archivePath', projectName + '.xcarchive', - '-exportOptionsPlist', exportOptionsPath, - '-exportPath', outputPath - ]; +function getXcodeArchiveArgs (projectName, projectPath, outputPath, exportOptionsPath) { + return [ + '-exportArchive', + '-archivePath', projectName + '.xcarchive', + '-exportOptionsPlist', exportOptionsPath, + '-exportPath', outputPath + ]; } -function parseBuildFlag(buildFlag, args) { +function parseBuildFlag (buildFlag, args) { var matched; for (var key in buildFlagMatchers) { var found = buildFlag.match(buildFlagMatchers[key]); @@ -342,7 +363,8 @@ function parseBuildFlag(buildFlag, args) { if (!matched) { // If the flag starts with a '-' then it is an xcodebuild built-in option or a // user-defined setting. The regex makes sure that we don't split a user-defined - // setting that is wrapped in quotes. + // setting that is wrapped in quotes. + /* eslint-disable no-useless-escape */ if (buildFlag[0] === '-' && !buildFlag.match(/^.*=(\".*\")|(\'.*\')$/)) { args.otherFlags = args.otherFlags.concat(buildFlag.split(' ')); events.emit('warn', util.format('Adding xcodebuildArg: %s', buildFlag.split(' '))); @@ -354,7 +376,7 @@ function parseBuildFlag(buildFlag, args) { } // help/usage function -module.exports.help = function help() { +module.exports.help = function help () { console.log(''); console.log('Usage: build [--debug | --release] [--archs=\"<list of architectures...>\"]'); console.log(' [--device | --simulator] [--codeSignIdentity=\"<identity>\"]'); @@ -365,6 +387,7 @@ module.exports.help = function help() { console.log(' --debug : Builds project in debug mode. (Default)'); console.log(' --release : Builds project in release mode.'); console.log(' -r : Shortcut :: builds project in release mode.'); + /* eslint-enable no-useless-escape */ // TODO: add support for building different archs // console.log(" --archs : Builds project binaries for specific chip architectures (`anycpu`, `arm`, `x86`, `x64`)."); console.log(' --device, --simulator'); diff --git a/StoneIsland/platforms/ios/cordova/lib/check_reqs.js b/StoneIsland/platforms/ios/cordova/lib/check_reqs.js index ae21f989..21a22081 100755 --- a/StoneIsland/platforms/ios/cordova/lib/check_reqs.js +++ b/StoneIsland/platforms/ios/cordova/lib/check_reqs.js @@ -17,29 +17,33 @@ under the License. */ -var Q = require('q'), - shell = require('shelljs'), - util = require('util'), - versions = require('./versions'); +'use strict'; -var XCODEBUILD_MIN_VERSION = '7.0.0'; -var XCODEBUILD_NOT_FOUND_MESSAGE = +const Q = require('q'); +const shell = require('shelljs'); +const util = require('util'); +const versions = require('./versions'); + +const SUPPORTED_OS_PLATFORMS = [ 'darwin' ]; + +const XCODEBUILD_MIN_VERSION = '7.0.0'; +const XCODEBUILD_NOT_FOUND_MESSAGE = 'Please install version ' + XCODEBUILD_MIN_VERSION + ' or greater from App Store'; -var IOS_DEPLOY_MIN_VERSION = '1.9.0'; -var IOS_DEPLOY_NOT_FOUND_MESSAGE = +const IOS_DEPLOY_MIN_VERSION = '1.9.2'; +const IOS_DEPLOY_NOT_FOUND_MESSAGE = 'Please download, build and install version ' + IOS_DEPLOY_MIN_VERSION + ' or greater' + ' from https://github.com/phonegap/ios-deploy into your path, or do \'npm install -g ios-deploy\''; -var COCOAPODS_MIN_VERSION = '1.0.1'; -var COCOAPODS_NOT_FOUND_MESSAGE = +const COCOAPODS_MIN_VERSION = '1.0.1'; +const COCOAPODS_NOT_FOUND_MESSAGE = 'Please install version ' + COCOAPODS_MIN_VERSION + ' or greater from https://cocoapods.org/'; -var COCOAPODS_NOT_SYNCED_MESSAGE = +const COCOAPODS_NOT_SYNCED_MESSAGE = 'The CocoaPods repo has not been synced yet, this will take a long time (approximately 500MB as of Sept 2016). Please run `pod setup` first to sync the repo.'; -var COCOAPODS_SYNCED_MIN_SIZE = 475; // in megabytes -var COCOAPODS_SYNC_ERROR_MESSAGE = +const COCOAPODS_SYNCED_MIN_SIZE = 475; // in megabytes +const COCOAPODS_SYNC_ERROR_MESSAGE = 'The CocoaPods repo has been created, but there appears to be a sync error. The repo size should be at least ' + COCOAPODS_SYNCED_MIN_SIZE + '. Please run `pod setup --verbose` to sync the repo.'; -var COCOAPODS_REPO_NOT_FOUND_MESSAGE = 'The CocoaPods repo at ~/.cocoapods was not found.'; +const COCOAPODS_REPO_NOT_FOUND_MESSAGE = 'The CocoaPods repo at ~/.cocoapods was not found.'; /** * Checks if xcode util is available @@ -59,13 +63,25 @@ module.exports.check_ios_deploy = function () { module.exports.check_os = function () { // Build iOS apps available for OSX platform only, so we reject on others platforms - return process.platform === 'darwin' ? + return os_platform_is_supported() ? Q.resolve(process.platform) : - Q.reject('Cordova tooling for iOS requires Apple OS X'); + Q.reject('Cordova tooling for iOS requires Apple macOS'); }; -function check_cocoapod_tool() { - return checkTool('pod', COCOAPODS_MIN_VERSION, COCOAPODS_NOT_FOUND_MESSAGE, 'CocoaPods'); +function os_platform_is_supported () { + return (SUPPORTED_OS_PLATFORMS.indexOf(process.platform) !== -1); +} + +function check_cocoapod_tool (toolChecker) { + toolChecker = toolChecker || checkTool; + if (os_platform_is_supported()) { // CB-12856 + return toolChecker('pod', COCOAPODS_MIN_VERSION, COCOAPODS_NOT_FOUND_MESSAGE, 'CocoaPods'); + } else { + return Q.resolve({ + 'ignore': true, + 'ignoreMessage': `CocoaPods check and installation ignored on ${process.platform}` + }); + } } /** @@ -74,47 +90,48 @@ function check_cocoapod_tool() { */ module.exports.check_cocoapods_repo_size = function () { return check_cocoapod_tool() - .then(function() { - // check size of ~/.cocoapods repo - var commandString = util.format('du -sh %s/.cocoapods', process.env.HOME); - var command = shell.exec(commandString, { silent:true }); - if (command.code !== 0) { // error, perhaps not found - return Q.reject(util.format('%s (%s)', COCOAPODS_REPO_NOT_FOUND_MESSAGE, command.output)); - } else { // success, parse output + .then(function (toolOptions) { + // check size of ~/.cocoapods repo + let commandString = util.format('du -sh %s/.cocoapods', process.env.HOME); + let command = shell.exec(commandString, { silent: true }); // command.output is e.g "750M path/to/.cocoapods", we just scan the number - return Q.resolve(parseFloat(command.output)); - } - }) - .then(function(repoSize) { - if (COCOAPODS_SYNCED_MIN_SIZE > repoSize) { - return Q.reject(COCOAPODS_SYNC_ERROR_MESSAGE); - } else { - return Q.resolve(); - } - }); + let size = toolOptions.ignore ? 0 : parseFloat(command.output); + + if (toolOptions.ignore || command.code === 0) { // success, parse output + return Q.resolve(size, toolOptions); + } else { // error, perhaps not found + return Q.reject(util.format('%s (%s)', COCOAPODS_REPO_NOT_FOUND_MESSAGE, command.output)); + } + }) + .then(function (repoSize, toolOptions) { + if (toolOptions.ignore || COCOAPODS_SYNCED_MIN_SIZE <= repoSize) { // success, expected size + return Q.resolve(toolOptions); + } else { + return Q.reject(COCOAPODS_SYNC_ERROR_MESSAGE); + } + }); }; /** * Checks if cocoapods is available, and whether the repo is synced (because it takes a long time to download) * @return {Promise} Returns a promise either resolved or rejected */ -module.exports.check_cocoapods = function () { - return check_cocoapod_tool() - // check whether the cocoapods repo has been synced through `pod repo` command - // a value of '0 repos' means it hasn't been synced - .then(function() { - var code = shell.exec('pod repo | grep -e "^0 repos"', { silent:true }).code; - return Q.resolve(code !== 0); // non-zero means it is synced (has 1 repo at least) - }) - .then(function(repoIsSynced) { - if (repoIsSynced) { - // return check_cocoapods_repo_size(); - // we could check the repo size above, but it takes too long. - return Q.resolve(); - } else { - return Q.reject(COCOAPODS_NOT_SYNCED_MESSAGE); - } - }); +module.exports.check_cocoapods = function (toolChecker) { + return check_cocoapod_tool(toolChecker) + // check whether the cocoapods repo has been synced through `pod repo` command + // a value of '0 repos' means it hasn't been synced + .then(function (toolOptions) { + let code = shell.exec('pod repo | grep -e "^0 repos"', { silent: true }).code; + let repoIsSynced = (code !== 0); + + if (toolOptions.ignore || repoIsSynced) { + // return check_cocoapods_repo_size(); + // we could check the repo size above, but it takes too long. + return Q.resolve(toolOptions); + } else { + return Q.reject(COCOAPODS_NOT_SYNCED_MESSAGE); + } + }); }; /** @@ -129,15 +146,16 @@ function checkTool (tool, minVersion, message, toolFriendlyName) { toolFriendlyName = toolFriendlyName || tool; // Check whether tool command is available at all - var tool_command = shell.which(tool); + let tool_command = shell.which(tool); if (!tool_command) { return Q.reject(toolFriendlyName + ' was not found. ' + (message || '')); } + // check if tool version is greater than specified one return versions.get_tool_version(tool).then(function (version) { version = version.trim(); return versions.compareVersions(version, minVersion) >= 0 ? - Q.resolve(version) : + Q.resolve({ 'version': version }) : Q.reject('Cordova needs ' + toolFriendlyName + ' version ' + minVersion + ' or greater, you have version ' + version + '. ' + (message || '')); }); @@ -150,7 +168,7 @@ function checkTool (tool, minVersion, message, toolFriendlyName) { * @param {Boolean} isFatal Marks the requirement as fatal. If such requirement will fail * next requirements' checks will be skipped. */ -var Requirement = function (id, name, isFatal) { +let Requirement = function (id, name, isFatal) { this.id = id; this.name = name; this.installed = false; @@ -164,19 +182,19 @@ var Requirement = function (id, name, isFatal) { * * @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 = [ - new Requirement('os', 'Apple OS X', true), + const requirements = [ + new Requirement('os', 'Apple macOS', true), new Requirement('xcode', 'Xcode'), new Requirement('ios-deploy', 'ios-deploy'), new Requirement('CocoaPods', 'CocoaPods') ]; - var result = []; - var fatalIsHit = false; + let result = []; + let fatalIsHit = false; - var checkFns = [ + let checkFns = [ module.exports.check_os, module.exports.check_xcodebuild, module.exports.check_ios_deploy, @@ -190,21 +208,21 @@ module.exports.check_all = function() { // we don't need to check others if (fatalIsHit) return Q(); - var requirement = requirements[idx]; + let requirement = requirements[idx]; return checkFn() - .then(function (version) { - requirement.installed = true; - requirement.metadata.version = version; - result.push(requirement); - }, function (err) { - if (requirement.isFatal) fatalIsHit = true; - requirement.metadata.reason = err; - result.push(requirement); - }); + .then(function (version) { + requirement.installed = true; + requirement.metadata.version = version; + result.push(requirement); + }, function (err) { + if (requirement.isFatal) fatalIsHit = true; + requirement.metadata.reason = err; + result.push(requirement); + }); }); }, Q()) - .then(function () { - // When chain is completed, return requirements array to upstream API - return result; - }); + .then(function () { + // When chain is completed, return requirements array to upstream API + return result; + }); }; diff --git a/StoneIsland/platforms/ios/cordova/lib/clean.js b/StoneIsland/platforms/ios/cordova/lib/clean.js index 7c8cf56e..20e8ac66 100755 --- a/StoneIsland/platforms/ios/cordova/lib/clean.js +++ b/StoneIsland/platforms/ios/cordova/lib/clean.js @@ -6,9 +6,9 @@ * 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 @@ -17,16 +17,14 @@ * under the License. */ -/*jshint node: true*/ - -var Q = require('q'), - path = require('path'), - shell = require('shelljs'), - spawn = require('./spawn'); +var Q = require('q'); +var path = require('path'); +var shell = require('shelljs'); +var spawn = require('./spawn'); var projectPath = path.join(__dirname, '..', '..'); -module.exports.run = function() { +module.exports.run = function () { var projectName = shell.ls(projectPath).filter(function (name) { return path.extname(name) === '.xcodeproj'; })[0]; @@ -36,9 +34,9 @@ module.exports.run = function() { } return spawn('xcodebuild', ['-project', projectName, '-configuration', 'Debug', '-alltargets', 'clean'], projectPath) - .then(function () { - return spawn('xcodebuild', ['-project', projectName, '-configuration', 'Release', '-alltargets', 'clean'], projectPath); - }).then(function () { - return shell.rm('-rf', path.join(projectPath, 'build')); - }); + .then(function () { + return spawn('xcodebuild', ['-project', projectName, '-configuration', 'Release', '-alltargets', 'clean'], projectPath); + }).then(function () { + return shell.rm('-rf', path.join(projectPath, 'build')); + }); }; diff --git a/StoneIsland/platforms/ios/cordova/lib/copy-www-build-step.js b/StoneIsland/platforms/ios/cordova/lib/copy-www-build-step.js index 7caa200f..e05aacf2 100755 --- a/StoneIsland/platforms/ios/cordova/lib/copy-www-build-step.js +++ b/StoneIsland/platforms/ios/cordova/lib/copy-www-build-step.js @@ -24,19 +24,19 @@ // This script should not be called directly. // It is called as a build step from Xcode. -var BUILT_PRODUCTS_DIR = process.env.BUILT_PRODUCTS_DIR, - FULL_PRODUCT_NAME = process.env.FULL_PRODUCT_NAME, - COPY_HIDDEN = process.env.COPY_HIDDEN, - PROJECT_FILE_PATH = process.env.PROJECT_FILE_PATH; +var BUILT_PRODUCTS_DIR = process.env.BUILT_PRODUCTS_DIR; +var FULL_PRODUCT_NAME = process.env.FULL_PRODUCT_NAME; +var COPY_HIDDEN = process.env.COPY_HIDDEN; +var PROJECT_FILE_PATH = process.env.PROJECT_FILE_PATH; -var path = require('path'), - fs = require('fs'), - shell = require('shelljs'), - srcDir = 'www', - dstDir = path.join(BUILT_PRODUCTS_DIR, FULL_PRODUCT_NAME), - dstWwwDir = path.join(dstDir, 'www'); +var path = require('path'); +var fs = require('fs'); +var shell = require('shelljs'); +var srcDir = 'www'; +var dstDir = path.join(BUILT_PRODUCTS_DIR, FULL_PRODUCT_NAME); +var dstWwwDir = path.join(dstDir, 'www'); -if(!BUILT_PRODUCTS_DIR) { +if (!BUILT_PRODUCTS_DIR) { console.error('The script is meant to be run as an Xcode build step and relies on env variables set by Xcode.'); process.exit(1); } @@ -57,13 +57,13 @@ shell.rm('-rf', path.join(dstDir, 'embedded.mobileprovision')); // Copy www dir recursively var code; -if(!!COPY_HIDDEN) { +if (COPY_HIDDEN) { code = shell.exec('rsync -Lra "' + srcDir + '" "' + dstDir + '"').code; } else { code = shell.exec('rsync -Lra --exclude="- .*" "' + srcDir + '" "' + dstDir + '"').code; } -if(code !== 0) { +if (code !== 0) { console.error('Error occured on copying www. Code: ' + code); process.exit(3); } diff --git a/StoneIsland/platforms/ios/cordova/lib/list-devices b/StoneIsland/platforms/ios/cordova/lib/list-devices index 3fa3e6da..047d5950 100755 --- a/StoneIsland/platforms/ios/cordova/lib/list-devices +++ b/StoneIsland/platforms/ios/cordova/lib/list-devices @@ -19,7 +19,6 @@ under the License. */ -/*jshint node: true*/ var Q = require('q'), exec = require('child_process').exec; diff --git a/StoneIsland/platforms/ios/cordova/lib/list-emulator-build-targets b/StoneIsland/platforms/ios/cordova/lib/list-emulator-build-targets index d17fc8ca..c0d566fb 100755 --- a/StoneIsland/platforms/ios/cordova/lib/list-emulator-build-targets +++ b/StoneIsland/platforms/ios/cordova/lib/list-emulator-build-targets @@ -19,7 +19,6 @@ under the License. */ -/*jshint node: true*/ var Q = require('q'), exec = require('child_process').exec; diff --git a/StoneIsland/platforms/ios/cordova/lib/list-emulator-images b/StoneIsland/platforms/ios/cordova/lib/list-emulator-images index 87a5ad27..d8be5766 100755 --- a/StoneIsland/platforms/ios/cordova/lib/list-emulator-images +++ b/StoneIsland/platforms/ios/cordova/lib/list-emulator-images @@ -19,7 +19,6 @@ under the License. */ -/*jshint node: true*/ var Q = require('q'), iossim = require('ios-sim'), diff --git a/StoneIsland/platforms/ios/cordova/lib/list-started-emulators b/StoneIsland/platforms/ios/cordova/lib/list-started-emulators index 1269e47a..710fa2f7 100755 --- a/StoneIsland/platforms/ios/cordova/lib/list-started-emulators +++ b/StoneIsland/platforms/ios/cordova/lib/list-started-emulators @@ -19,7 +19,6 @@ under the License. */ -/*jshint node: true*/ var Q = require('q'), exec = require('child_process').exec; diff --git a/StoneIsland/platforms/ios/cordova/lib/plugman/pluginHandlers.js b/StoneIsland/platforms/ios/cordova/lib/plugman/pluginHandlers.js index 416aba96..1f6920fa 100755 --- a/StoneIsland/platforms/ios/cordova/lib/plugman/pluginHandlers.js +++ b/StoneIsland/platforms/ios/cordova/lib/plugman/pluginHandlers.js @@ -30,27 +30,27 @@ var keep_these_frameworks = [ ]; var handlers = { - 'source-file':{ - install:function(obj, plugin, project, options) { + 'source-file': { + install: function (obj, plugin, project, options) { installHelper('source-file', obj, plugin.dir, project.projectDir, plugin.id, options, project); }, - uninstall:function(obj, plugin, project, options) { + uninstall: function (obj, plugin, project, options) { uninstallHelper('source-file', obj, project.projectDir, plugin.id, options, project); } }, - 'header-file':{ - install:function(obj, plugin, project, options) { + 'header-file': { + install: function (obj, plugin, project, options) { installHelper('header-file', obj, plugin.dir, project.projectDir, plugin.id, options, project); }, - uninstall:function(obj, plugin, project, options) { + uninstall: function (obj, plugin, project, options) { uninstallHelper('header-file', obj, project.projectDir, plugin.id, options, project); } }, - 'resource-file':{ - install:function(obj, plugin, project, options) { - var src = obj.src, - target = obj.target, - srcFile = path.resolve(plugin.dir, src); + 'resource-file': { + install: function (obj, plugin, project, options) { + var src = obj.src; + var target = obj.target; + var srcFile = path.resolve(plugin.dir, src); if (!target) { target = path.basename(src); @@ -67,9 +67,9 @@ var handlers = { var link = !!(options && options.link); copyFile(plugin.dir, src, project.projectDir, destFile, link); }, - uninstall:function(obj, plugin, project, options) { - var src = obj.src, - target = obj.target; + uninstall: function (obj, plugin, project, options) { + var src = obj.src; + var target = obj.target; if (!target) { target = path.basename(src); @@ -80,19 +80,19 @@ var handlers = { shell.rm('-rf', destFile); } }, - 'framework':{ // CB-5238 custom frameworks only - install:function(obj, plugin, project, options) { - var src = obj.src, - custom = !!(obj.custom), // convert to boolean (if truthy/falsy) - embed = !!(obj.embed), // convert to boolean (if truthy/falsy) - link = !embed; // either link or embed can be true, but not both. the other has to be false - + 'framework': { // CB-5238 custom frameworks only + install: function (obj, plugin, project, options) { + var src = obj.src; + var custom = !!(obj.custom); // convert to boolean (if truthy/falsy) + var embed = !!(obj.embed); // convert to boolean (if truthy/falsy) + var link = !embed; // either link or embed can be true, but not both. the other has to be false + if (!custom) { var keepFrameworks = keep_these_frameworks; if (keepFrameworks.indexOf(src) < 0) { if (obj.type === 'podspec') { - //podspec handled in Api.js + // podspec handled in Api.js } else { project.frameworks[src] = project.frameworks[src] || 0; project.frameworks[src]++; @@ -104,8 +104,8 @@ var handlers = { } return; } - var srcFile = path.resolve(plugin.dir, src), - targetDir = path.resolve(project.plugins_dir, plugin.id, path.basename(src)); + var srcFile = path.resolve(plugin.dir, src); + var targetDir = path.resolve(project.plugins_dir, plugin.id, path.basename(src)); if (!fs.existsSync(srcFile)) throw new CordovaError('Cannot find framework "' + srcFile + '" for plugin ' + plugin.id + ' in iOS platform'); if (fs.existsSync(targetDir)) throw new CordovaError('Framework "' + targetDir + '" for plugin ' + plugin.id + ' already exists in iOS platform'); var symlink = !!(options && options.link); @@ -123,23 +123,23 @@ var handlers = { project.xcode.addFramework(project_relative, opt); events.emit('verbose', util.format('Custom framework added to project. %s -> %s', src, JSON.stringify(opt))); }, - uninstall:function(obj, plugin, project, options) { + uninstall: function (obj, plugin, project, options) { var src = obj.src; - if (!obj.custom) { //CB-9825 cocoapod integration for plugins + if (!obj.custom) { // CB-9825 cocoapod integration for plugins var keepFrameworks = keep_these_frameworks; if (keepFrameworks.indexOf(src) < 0) { if (obj.type === 'podspec') { var podsJSON = require(path.join(project.projectDir, 'pods.json')); - if(podsJSON[src]) { - if(podsJSON[src].count > 1) { + if (podsJSON[src]) { + if (podsJSON[src].count > 1) { podsJSON[src].count = podsJSON[src].count - 1; } else { delete podsJSON[src]; } } } else { - //this should be refactored + // this should be refactored project.frameworks[src] = project.frameworks[src] || 1; project.frameworks[src]--; if (project.frameworks[src] < 1) { @@ -153,8 +153,8 @@ var handlers = { return; } - var targetDir = fixPathSep(path.resolve(project.plugins_dir, plugin.id, path.basename(src))), - pbxFile = project.xcode.removeFramework(targetDir, {customFramework: true}); + var targetDir = fixPathSep(path.resolve(project.plugins_dir, plugin.id, path.basename(src))); + var pbxFile = project.xcode.removeFramework(targetDir, {customFramework: true}); if (pbxFile) { project.xcode.removeFromPbxEmbedFrameworksBuildPhase(pbxFile); } @@ -162,15 +162,15 @@ var handlers = { } }, 'lib-file': { - install:function(obj, plugin, project, options) { + install: function (obj, plugin, project, options) { events.emit('verbose', '<lib-file> install is not supported for iOS plugins'); }, - uninstall:function(obj, plugin, project, options) { + uninstall: function (obj, plugin, project, options) { events.emit('verbose', '<lib-file> uninstall is not supported for iOS plugins'); } }, - 'asset':{ - install:function(obj, plugin, project, options) { + 'asset': { + install: function (obj, plugin, project, options) { if (!obj.src) { throw new CordovaError(generateAttributeError('src', 'asset', plugin.id)); } @@ -181,7 +181,7 @@ var handlers = { copyFile(plugin.dir, obj.src, project.www, obj.target); if (options && options.usePlatformWww) copyFile(plugin.dir, obj.src, project.platformWww, obj.target); }, - uninstall:function(obj, plugin, project, options) { + uninstall: function (obj, plugin, project, options) { var target = obj.target; if (!target) { @@ -200,7 +200,7 @@ var handlers = { 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.basename(obj.src, path.extname (obj.src))); + var moduleName = plugin.id + '.' + (obj.name || path.basename(obj.src, path.extname(obj.src))); // Read in the file, prepend the cordova.define, and write it back out. var scriptContent = fs.readFileSync(moduleSource, 'utf-8').replace(/^\ufeff/, ''); // Window BOM @@ -234,7 +234,7 @@ module.exports.getInstaller = function (type) { events.emit('warn', '<' + type + '> is not supported for iOS plugins'); }; -module.exports.getUninstaller = function(type) { +module.exports.getUninstaller = function (type) { if (handlers[type] && handlers[type].uninstall) { return handlers[type].uninstall; } @@ -242,7 +242,7 @@ module.exports.getUninstaller = function(type) { events.emit('warn', '<' + type + '> is not supported for iOS plugins'); }; -function installHelper(type, obj, plugin_dir, project_dir, plugin_id, options, project) { +function installHelper (type, obj, plugin_dir, project_dir, plugin_id, options, project) { var srcFile = path.resolve(plugin_dir, obj.src); var targetDir = path.resolve(project.plugins_dir, plugin_id, obj.targetDir || ''); var destFile = path.join(targetDir, path.basename(obj.src)); @@ -271,19 +271,19 @@ function installHelper(type, obj, plugin_dir, project_dir, plugin_id, options, p project_ref = 'Plugins/' + fixPathSep(path.relative(project.plugins_dir, destFile)); } - if (type == 'header-file') { + if (type === 'header-file') { project.xcode.addHeaderFile(project_ref); } else if (obj.framework) { var opt = { weak: obj.weak }; var project_relative = path.join(path.basename(project.xcode_path), project_ref); project.xcode.addFramework(project_relative, opt); - project.xcode.addToLibrarySearchPaths({path:project_ref}); + project.xcode.addToLibrarySearchPaths({path: project_ref}); } else { - project.xcode.addSourceFile(project_ref, obj.compilerFlags ? {compilerFlags:obj.compilerFlags} : {}); + project.xcode.addSourceFile(project_ref, obj.compilerFlags ? {compilerFlags: obj.compilerFlags} : {}); } } -function uninstallHelper(type, obj, project_dir, plugin_id, options, project) { +function uninstallHelper (type, obj, project_dir, plugin_id, options, project) { var targetDir = path.resolve(project.plugins_dir, plugin_id, obj.targetDir || ''); var destFile = path.join(targetDir, path.basename(obj.src)); @@ -298,19 +298,19 @@ function uninstallHelper(type, obj, project_dir, plugin_id, options, project) { shell.rm('-rf', targetDir); - if (type == 'header-file') { + if (type === 'header-file') { project.xcode.removeHeaderFile(project_ref); } else if (obj.framework) { var project_relative = path.join(path.basename(project.xcode_path), project_ref); project.xcode.removeFramework(project_relative); - project.xcode.removeFromLibrarySearchPaths({path:project_ref}); + project.xcode.removeFromLibrarySearchPaths({path: project_ref}); } else { project.xcode.removeSourceFile(project_ref); } } -var pathSepFix = new RegExp(path.sep.replace(/\\/,'\\\\'),'g'); -function fixPathSep(file) { +var pathSepFix = new RegExp(path.sep.replace(/\\/, '\\\\'), 'g'); +function fixPathSep (file) { return file.replace(pathSepFix, '/'); } @@ -321,14 +321,12 @@ function copyFile (plugin_dir, src, project_dir, dest, link) { // 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('File "' + src + '" is located outside the plugin directory "' + plugin_dir + '"'); + if (real_path.indexOf(real_plugin_path) !== 0) { throw new CordovaError('File "' + src + '" is located outside the plugin directory "' + plugin_dir + '"'); } dest = path.resolve(project_dir, dest); // check that dest path is located in project directory - if (dest.indexOf(project_dir) !== 0) - throw new CordovaError('Destination "' + dest + '" for source file "' + src + '" is located outside the project'); + if (dest.indexOf(project_dir) !== 0) { throw new CordovaError('Destination "' + dest + '" for source file "' + src + '" is located outside the project'); } shell.mkdir('-p', path.dirname(dest)); @@ -345,24 +343,22 @@ function copyFile (plugin_dir, src, project_dir, dest, link) { // 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!'); + if (fs.existsSync(target_path)) { throw new CordovaError('"' + target_path + '" already exists!'); } copyFile(plugin_dir, src, project_dir, dest, !!link); } -function linkFileOrDirTree(src, dest) { +function linkFileOrDirTree (src, dest) { if (fs.existsSync(dest)) { shell.rm('-Rf', dest); } if (fs.statSync(src).isDirectory()) { shell.mkdir('-p', dest); - fs.readdirSync(src).forEach(function(entry) { + fs.readdirSync(src).forEach(function (entry) { linkFileOrDirTree(path.join(src, entry), path.join(dest, entry)); }); - } - else { + } else { fs.linkSync(src, dest); } } @@ -388,8 +384,8 @@ function removeFileAndParents (baseDir, destFile, stopper) { // 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) { + while (curDir !== path.resolve(baseDir, stopper)) { + if (fs.existsSync(curDir) && fs.readdirSync(curDir).length === 0) { fs.rmdirSync(curDir); curDir = path.resolve(curDir, '..'); } else { @@ -399,6 +395,6 @@ function removeFileAndParents (baseDir, destFile, stopper) { } } -function generateAttributeError(attribute, element, id) { +function generateAttributeError (attribute, element, id) { return 'Required attribute "' + attribute + '" not specified in <' + element + '> element from plugin: ' + id; } diff --git a/StoneIsland/platforms/ios/cordova/lib/prepare.js b/StoneIsland/platforms/ios/cordova/lib/prepare.js index c02c187f..17bbfeb7 100755 --- a/StoneIsland/platforms/ios/cordova/lib/prepare.js +++ b/StoneIsland/platforms/ios/cordova/lib/prepare.js @@ -37,15 +37,13 @@ var FileUpdater = require('cordova-common').FileUpdater; var projectFile = require('./projectFile'); // launch storyboard and related constants -var LAUNCHIMAGE_BUILD_SETTING = 'ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME'; +var LAUNCHIMAGE_BUILD_SETTING = 'ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME'; var LAUNCHIMAGE_BUILD_SETTING_VALUE = 'LaunchImage'; var UI_LAUNCH_STORYBOARD_NAME = 'UILaunchStoryboardName'; var CDV_LAUNCH_STORYBOARD_NAME = 'CDVLaunchScreen'; var IMAGESET_COMPACT_SIZE_CLASS = 'compact'; var CDV_ANY_SIZE_CLASS = 'any'; -/*jshint sub:true*/ - module.exports.prepare = function (cordovaProject, options) { var self = this; @@ -56,19 +54,19 @@ module.exports.prepare = function (cordovaProject, options) { // Update own www dir with project's www assets and plugins' assets and js-files return Q.when(updateWww(cordovaProject, this.locations)) - .then(function () { - // update project according to config.xml changes. - return updateProject(self._config, self.locations); - }) - .then(function () { - updateIcons(cordovaProject, self.locations); - updateSplashScreens(cordovaProject, self.locations); - updateLaunchStoryboardImages(cordovaProject, self.locations); - updateFileResources(cordovaProject, self.locations); - }) - .then(function () { - events.emit('verbose', 'Prepared iOS project successfully'); - }); + .then(function () { + // update project according to config.xml changes. + return updateProject(self._config, self.locations); + }) + .then(function () { + updateIcons(cordovaProject, self.locations); + updateSplashScreens(cordovaProject, self.locations); + updateLaunchStoryboardImages(cordovaProject, self.locations); + updateFileResources(cordovaProject, self.locations); + }) + .then(function () { + events.emit('verbose', 'Prepared iOS project successfully'); + }); }; module.exports.clean = function (options) { @@ -109,7 +107,7 @@ module.exports.clean = function (options) { * represents current project's configuration. When returned, the * configuration is already dumped to appropriate config.xml file. */ -function updateConfigFile(sourceConfig, configMunger, locations) { +function updateConfigFile (sourceConfig, configMunger, locations) { events.emit('verbose', 'Generating platform-specific config.xml from defaults for iOS at ' + locations.configXml); // First cleanup current config and merge project's one into own @@ -124,7 +122,7 @@ function updateConfigFile(sourceConfig, configMunger, locations) { // 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(), 'ios', /*clobber=*/true); + config.doc.getroot(), 'ios', /* clobber= */true); config.write(); return config; @@ -133,7 +131,7 @@ function updateConfigFile(sourceConfig, configMunger, locations) { /** * Logs all file operations via the verbose event stream, indented. */ -function logFileOp(message) { +function logFileOp (message) { events.emit('verbose', ' ' + message); } @@ -146,7 +144,7 @@ function logFileOp(message) { * @param {boolean} destinations An object that contains destinations * paths for www files. */ -function updateWww(cordovaProject, destinations) { +function updateWww (cordovaProject, destinations) { var sourceDirs = [ path.relative(cordovaProject.root, cordovaProject.locations.www), path.relative(cordovaProject.root, destinations.platformWww) @@ -169,7 +167,7 @@ function updateWww(cordovaProject, destinations) { /** * Cleans all files from the platform 'www' directory. */ -function cleanWww(projectRoot, locations) { +function cleanWww (projectRoot, locations) { var targetDir = path.relative(projectRoot, locations.www); events.emit('verbose', 'Cleaning ' + targetDir); @@ -185,7 +183,7 @@ function cleanWww(projectRoot, locations) { * be used to update project * @param {Object} locations A map of locations for this platform (In/Out) */ -function updateProject(platformConfig, locations) { +function updateProject (platformConfig, locations) { // CB-6992 it is necessary to normalize characters // because node and shell scripts handles unicode symbols differently @@ -193,6 +191,7 @@ function updateProject(platformConfig, locations) { var name = unorm.nfd(platformConfig.name()); var pkg = platformConfig.getAttribute('ios-CFBundleIdentifier') || platformConfig.packageName(); var version = platformConfig.version(); + var displayName = platformConfig.shortName && platformConfig.shortName(); var originalName = path.basename(locations.xcodeCordovaProj); @@ -210,6 +209,10 @@ function updateProject(platformConfig, locations) { infoPlist['CFBundleDevelopmentRegion'] = platformConfig.getAttribute('defaultlocale'); } + if (displayName) { + infoPlist['CFBundleDisplayName'] = displayName; + } + // replace Info.plist ATS entries according to <access> and <allow-navigation> config.xml entries var ats = writeATSEntries(platformConfig); if (Object.keys(ats).length > 0) { @@ -222,16 +225,16 @@ function updateProject(platformConfig, locations) { updateProjectPlistForLaunchStoryboard(platformConfig, infoPlist); var info_contents = plist.build(infoPlist); - info_contents = info_contents.replace(/<string>[\s\r\n]*<\/string>/g,'<string></string>'); + info_contents = info_contents.replace(/<string>[\s\r\n]*<\/string>/g, '<string></string>'); fs.writeFileSync(plistFile, info_contents, 'utf-8'); events.emit('verbose', 'Wrote out iOS Bundle Identifier "' + pkg + '" and iOS Bundle Version "' + version + '" to ' + plistFile); - return handleBuildSettings(platformConfig, locations, infoPlist).then(function() { - if (name == originalName) { + return handleBuildSettings(platformConfig, locations, infoPlist).then(function () { + if (name === originalName) { events.emit('verbose', 'iOS Product Name has not changed (still "' + originalName + '")'); return Q(); } else { // CB-11712 <name> was changed, we don't support it' - var errorString = + var errorString = 'The product name change (<name> tag) in config.xml is not supported dynamically.\n' + 'To change your product name, you have to remove, then add your ios platform again.\n' + 'Make sure you save your plugins beforehand using `cordova plugin save`.\n' + @@ -245,43 +248,43 @@ function updateProject(platformConfig, locations) { }); } -function handleOrientationSettings(platformConfig, infoPlist) { +function handleOrientationSettings (platformConfig, infoPlist) { switch (getOrientationValue(platformConfig)) { - case 'portrait': - infoPlist['UIInterfaceOrientation'] = [ 'UIInterfaceOrientationPortrait' ]; - infoPlist['UISupportedInterfaceOrientations'] = [ 'UIInterfaceOrientationPortrait', 'UIInterfaceOrientationPortraitUpsideDown' ]; - infoPlist['UISupportedInterfaceOrientations~ipad'] = [ 'UIInterfaceOrientationPortrait', 'UIInterfaceOrientationPortraitUpsideDown' ]; - break; - case 'landscape': - infoPlist['UIInterfaceOrientation'] = [ 'UIInterfaceOrientationLandscapeLeft' ]; - infoPlist['UISupportedInterfaceOrientations'] = [ 'UIInterfaceOrientationLandscapeLeft', 'UIInterfaceOrientationLandscapeRight' ]; - infoPlist['UISupportedInterfaceOrientations~ipad'] = [ 'UIInterfaceOrientationLandscapeLeft', 'UIInterfaceOrientationLandscapeRight' ]; - break; - case 'all': - infoPlist['UIInterfaceOrientation'] = [ 'UIInterfaceOrientationPortrait' ]; - infoPlist['UISupportedInterfaceOrientations'] = [ 'UIInterfaceOrientationPortrait', 'UIInterfaceOrientationPortraitUpsideDown', 'UIInterfaceOrientationLandscapeLeft', 'UIInterfaceOrientationLandscapeRight' ]; - infoPlist['UISupportedInterfaceOrientations~ipad'] = [ 'UIInterfaceOrientationPortrait', 'UIInterfaceOrientationPortraitUpsideDown', 'UIInterfaceOrientationLandscapeLeft', 'UIInterfaceOrientationLandscapeRight' ]; - break; - case 'default': - infoPlist['UISupportedInterfaceOrientations'] = [ 'UIInterfaceOrientationPortrait', 'UIInterfaceOrientationLandscapeLeft', 'UIInterfaceOrientationLandscapeRight' ]; - infoPlist['UISupportedInterfaceOrientations~ipad'] = [ 'UIInterfaceOrientationPortrait', 'UIInterfaceOrientationPortraitUpsideDown', 'UIInterfaceOrientationLandscapeLeft', 'UIInterfaceOrientationLandscapeRight' ]; - delete infoPlist['UIInterfaceOrientation']; + case 'portrait': + infoPlist['UIInterfaceOrientation'] = [ 'UIInterfaceOrientationPortrait' ]; + infoPlist['UISupportedInterfaceOrientations'] = [ 'UIInterfaceOrientationPortrait', 'UIInterfaceOrientationPortraitUpsideDown' ]; + infoPlist['UISupportedInterfaceOrientations~ipad'] = [ 'UIInterfaceOrientationPortrait', 'UIInterfaceOrientationPortraitUpsideDown' ]; + break; + case 'landscape': + infoPlist['UIInterfaceOrientation'] = [ 'UIInterfaceOrientationLandscapeLeft' ]; + infoPlist['UISupportedInterfaceOrientations'] = [ 'UIInterfaceOrientationLandscapeLeft', 'UIInterfaceOrientationLandscapeRight' ]; + infoPlist['UISupportedInterfaceOrientations~ipad'] = [ 'UIInterfaceOrientationLandscapeLeft', 'UIInterfaceOrientationLandscapeRight' ]; + break; + case 'all': + infoPlist['UIInterfaceOrientation'] = [ 'UIInterfaceOrientationPortrait' ]; + infoPlist['UISupportedInterfaceOrientations'] = [ 'UIInterfaceOrientationPortrait', 'UIInterfaceOrientationPortraitUpsideDown', 'UIInterfaceOrientationLandscapeLeft', 'UIInterfaceOrientationLandscapeRight' ]; + infoPlist['UISupportedInterfaceOrientations~ipad'] = [ 'UIInterfaceOrientationPortrait', 'UIInterfaceOrientationPortraitUpsideDown', 'UIInterfaceOrientationLandscapeLeft', 'UIInterfaceOrientationLandscapeRight' ]; + break; + case 'default': + infoPlist['UISupportedInterfaceOrientations'] = [ 'UIInterfaceOrientationPortrait', 'UIInterfaceOrientationLandscapeLeft', 'UIInterfaceOrientationLandscapeRight' ]; + infoPlist['UISupportedInterfaceOrientations~ipad'] = [ 'UIInterfaceOrientationPortrait', 'UIInterfaceOrientationPortraitUpsideDown', 'UIInterfaceOrientationLandscapeLeft', 'UIInterfaceOrientationLandscapeRight' ]; + delete infoPlist['UIInterfaceOrientation']; } } -function handleBuildSettings(platformConfig, locations, infoPlist) { +function handleBuildSettings (platformConfig, locations, infoPlist) { var targetDevice = parseTargetDevicePreference(platformConfig.getPreference('target-device', 'ios')); var deploymentTarget = platformConfig.getPreference('deployment-target', 'ios'); var needUpdatedBuildSettingsForLaunchStoryboard = checkIfBuildSettingsNeedUpdatedForLaunchStoryboard(platformConfig, infoPlist); - // no build settings provided and we don't need to update build settings for launch storyboards, + // no build settings provided and we don't need to update build settings for launch storyboards, // then we don't need to parse and update .pbxproj file if (!targetDevice && !deploymentTarget && !needUpdatedBuildSettingsForLaunchStoryboard) { return Q(); } - var proj = new xcode.project(locations.pbxproj); + var proj = new xcode.project(locations.pbxproj); /* eslint new-cap : 0 */ try { proj.parseSync(); @@ -306,26 +309,37 @@ function handleBuildSettings(platformConfig, locations, infoPlist) { return Q(); } -function mapIconResources(icons, iconsDir) { +function mapIconResources (icons, iconsDir) { // See https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/MobileHIG/IconMatrix.html // for launch images sizes reference. var platformIcons = [ + {dest: 'icon-20.png', width: 20, height: 20}, + {dest: 'icon-20@2x.png', width: 40, height: 40}, + {dest: 'icon-20@3x.png', width: 60, height: 60}, + {dest: 'icon-40.png', width: 40, height: 40}, + {dest: 'icon-50.png', width: 50, height: 50}, + {dest: 'icon-50@2x.png', width: 100, height: 100}, {dest: 'icon-60@2x.png', width: 120, height: 120}, {dest: 'icon-60@3x.png', width: 180, height: 180}, + {dest: 'icon-72.png', width: 72, height: 72}, + {dest: 'icon-72@2x.png', width: 144, height: 144}, {dest: 'icon-76.png', width: 76, height: 76}, {dest: 'icon-76@2x.png', width: 152, height: 152}, + {dest: 'icon-83.5@2x.png', width: 167, height: 167}, + {dest: 'icon-1024.png', width: 1024, height: 1024}, {dest: 'icon-small.png', width: 29, height: 29}, {dest: 'icon-small@2x.png', width: 58, height: 58}, - {dest: 'icon-40.png', width: 40, height: 40}, - {dest: 'icon-40@2x.png', width: 80, height: 80}, {dest: 'icon-small@3x.png', width: 87, height: 87}, {dest: 'icon.png', width: 57, height: 57}, {dest: 'icon@2x.png', width: 114, height: 114}, - {dest: 'icon-72.png', width: 72, height: 72}, - {dest: 'icon-72@2x.png', width: 144, height: 144}, - {dest: 'icon-50.png', width: 50, height: 50}, - {dest: 'icon-50@2x.png', width: 100, height: 100}, - {dest: 'icon-83.5@2x.png', width: 167, height: 167} + {dest: 'AppIcon24x24@2x.png', width: 48, height: 48}, + {dest: 'AppIcon27.5x27.5@2x.png', width: 55, height: 55}, + {dest: 'AppIcon29x29@2x.png', width: 58, height: 58}, + {dest: 'AppIcon29x29@3x.png', width: 87, height: 87}, + {dest: 'AppIcon40x40@2x.png', width: 80, height: 80}, + {dest: 'AppIcon44x44@2x.png', width: 88, height: 88}, + {dest: 'AppIcon86x86@2x.png', width: 172, height: 172}, + {dest: 'AppIcon98x98@2x.png', width: 196, height: 196} ]; var pathMap = {}; @@ -339,7 +353,7 @@ function mapIconResources(icons, iconsDir) { return pathMap; } -function getIconsDir(projectRoot, platformProjDir) { +function getIconsDir (projectRoot, platformProjDir) { var iconsDir; var xcassetsExists = folderExists(path.join(projectRoot, platformProjDir, 'Images.xcassets/')); @@ -352,7 +366,7 @@ function getIconsDir(projectRoot, platformProjDir) { return iconsDir; } -function updateIcons(cordovaProject, locations) { +function updateIcons (cordovaProject, locations) { var icons = cordovaProject.projectConfig.getIcons('ios'); if (icons.length === 0) { @@ -368,7 +382,7 @@ function updateIcons(cordovaProject, locations) { resourceMap, { rootDir: cordovaProject.root }, logFileOp); } -function cleanIcons(projectRoot, projectConfig, locations) { +function cleanIcons (projectRoot, projectConfig, locations) { var icons = projectConfig.getIcons('ios'); if (icons.length > 0) { var platformProjDir = path.relative(projectRoot, locations.xcodeCordovaProj); @@ -385,7 +399,7 @@ function cleanIcons(projectRoot, projectConfig, locations) { } } -function mapSplashScreenResources(splashScreens, splashScreensDir) { +function mapSplashScreenResources (splashScreens, splashScreensDir) { var platformSplashScreens = [ {dest: 'Default~iphone.png', width: 320, height: 480}, {dest: 'Default@2x~iphone.png', width: 640, height: 960}, @@ -410,7 +424,7 @@ function mapSplashScreenResources(splashScreens, splashScreensDir) { return pathMap; } -function getSplashScreensDir(projectRoot, platformProjDir) { +function getSplashScreensDir (projectRoot, platformProjDir) { var splashScreensDir; var xcassetsExists = folderExists(path.join(projectRoot, platformProjDir, 'Images.xcassets/')); @@ -423,7 +437,7 @@ function getSplashScreensDir(projectRoot, platformProjDir) { return splashScreensDir; } -function updateSplashScreens(cordovaProject, locations) { +function updateSplashScreens (cordovaProject, locations) { var splashScreens = cordovaProject.projectConfig.getSplashScreens('ios'); if (splashScreens.length === 0) { @@ -439,7 +453,7 @@ function updateSplashScreens(cordovaProject, locations) { resourceMap, { rootDir: cordovaProject.root }, logFileOp); } -function cleanSplashScreens(projectRoot, projectConfig, locations) { +function cleanSplashScreens (projectRoot, projectConfig, locations) { var splashScreens = projectConfig.getSplashScreens('ios'); if (splashScreens.length > 0) { var platformProjDir = path.relative(projectRoot, locations.xcodeCordovaProj); @@ -456,7 +470,7 @@ function cleanSplashScreens(projectRoot, projectConfig, locations) { } } -function updateFileResources(cordovaProject, locations) { +function updateFileResources (cordovaProject, locations) { const platformDir = path.relative(cordovaProject.root, locations.root); const files = cordovaProject.projectConfig.getFileResources('ios'); @@ -469,9 +483,9 @@ function updateFileResources(cordovaProject, locations) { } let resourceMap = {}; - files.forEach(function(res) { - let src = res.src, - target = res.target; + files.forEach(function (res) { + let src = res.src; + let target = res.target; if (!target) { target = src; @@ -480,8 +494,7 @@ function updateFileResources(cordovaProject, locations) { let targetPath = path.join(project.resources_dir, target); targetPath = path.relative(cordovaProject.root, targetPath); - const resfile = path.join('Resources', path.relative(project.resources_dir, targetPath)); - project.xcode.addResourceFile(resfile); + project.xcode.addResourceFile(target); resourceMap[targetPath] = src; }); @@ -493,18 +506,18 @@ function updateFileResources(cordovaProject, locations) { project.write(); } -function cleanFileResources(projectRoot, projectConfig, locations) { +function cleanFileResources (projectRoot, projectConfig, locations) { const platformDir = path.relative(projectRoot, locations.root); - const files = projectConfig.getFileResources('ios'); + const files = projectConfig.getFileResources('ios', true); if (files.length > 0) { events.emit('verbose', 'Cleaning resource files at ' + platformDir); const project = projectFile.parse(locations); var resourceMap = {}; - files.forEach(function(res) { - let src = res.src, - target = res.target; + files.forEach(function (res) { + let src = res.src; + let target = res.target; if (!target) { target = src; @@ -519,7 +532,7 @@ function cleanFileResources(projectRoot, projectConfig, locations) { }); FileUpdater.updatePaths( - resourceMap, { rootDir: projectRoot, all: true}, logFileOp); + resourceMap, {rootDir: projectRoot, all: true}, logFileOp); project.write(); } @@ -531,9 +544,9 @@ function cleanFileResources(projectRoot, projectConfig, locations) { * combinations are returned, but not all will have a `filename` property. If the latter isn't present, * the device won't attempt to load an image matching the same traits. If the filename is present, * the device will try to load the image if it corresponds to the traits. - * + * * The resulting return looks like this: - * + * * [ * { * idiom: 'universal|ipad|iphone', @@ -545,12 +558,12 @@ function cleanFileResources(projectRoot, projectConfig, locations) { * target: undefined|'path/to/asset/library/Default@scale~idiom~widthheight.png' * }, ... * ] - * + * * @param {Array<Object>} splashScreens splash screens as defined in config.xml for this platform * @param {string} launchStoryboardImagesDir project-root/Images.xcassets/LaunchStoryboard.imageset/ * @return {Array<Object>} */ -function mapLaunchStoryboardContents(splashScreens, launchStoryboardImagesDir) { +function mapLaunchStoryboardContents (splashScreens, launchStoryboardImagesDir) { var platformLaunchStoryboardImages = []; var idioms = ['universal', 'ipad', 'iphone']; var scalesForIdiom = { @@ -562,8 +575,8 @@ function mapLaunchStoryboardContents(splashScreens, launchStoryboardImagesDir) { idioms.forEach(function (idiom) { scalesForIdiom[idiom].forEach(function (scale) { - sizes.forEach(function(width) { - sizes.forEach(function(height) { + sizes.forEach(function (width) { + sizes.forEach(function (height) { var item = { idiom: idiom, scale: scale, @@ -572,7 +585,7 @@ function mapLaunchStoryboardContents(splashScreens, launchStoryboardImagesDir) { }; /* examples of the search pattern: - * scale ~ idiom ~ width height + * scale ~ idiom ~ width height * @2x ~ universal ~ any any * @3x ~ iphone ~ com any * @2x ~ ipad ~ com any @@ -605,20 +618,20 @@ function mapLaunchStoryboardContents(splashScreens, launchStoryboardImagesDir) { /** * Returns a dictionary representing the source and destination paths for the launch storyboard images - * that need to be copied. - * + * that need to be copied. + * * The resulting return looks like this: - * + * * { * 'target-path': 'source-path', * ... * } - * + * * @param {Array<Object>} splashScreens splash screens as defined in config.xml for this platform * @param {string} launchStoryboardImagesDir project-root/Images.xcassets/LaunchStoryboard.imageset/ * @return {Object} */ -function mapLaunchStoryboardResources(splashScreens, launchStoryboardImagesDir) { +function mapLaunchStoryboardResources (splashScreens, launchStoryboardImagesDir) { var platformLaunchStoryboardImages = mapLaunchStoryboardContents(splashScreens, launchStoryboardImagesDir); var pathMap = {}; platformLaunchStoryboardImages.forEach(function (item) { @@ -630,10 +643,10 @@ function mapLaunchStoryboardResources(splashScreens, launchStoryboardImagesDir) } /** - * Builds the object that represents the contents.json file for the LaunchStoryboard image set. - * + * Builds the object that represents the contents.json file for the LaunchStoryboard image set. + * * The resulting return looks like this: - * + * * { * images: [ * { @@ -648,15 +661,15 @@ function mapLaunchStoryboardResources(splashScreens, launchStoryboardImagesDir) * version: 1 * } * } - * + * * A bit of minor logic is used to map from the array of images returned from mapLaunchStoryboardContents * to the format requried by Xcode. - * + * * @param {Array<Object>} splashScreens splash screens as defined in config.xml for this platform * @param {string} launchStoryboardImagesDir project-root/Images.xcassets/LaunchStoryboard.imageset/ * @return {Object} */ -function getLaunchStoryboardContentsJSON(splashScreens, launchStoryboardImagesDir) { +function getLaunchStoryboardContentsJSON (splashScreens, launchStoryboardImagesDir) { var platformLaunchStoryboardImages = mapLaunchStoryboardContents(splashScreens, launchStoryboardImagesDir); var contentsJSON = { @@ -666,14 +679,14 @@ function getLaunchStoryboardContentsJSON(splashScreens, launchStoryboardImagesDi version: 1 } }; - contentsJSON.images = platformLaunchStoryboardImages.map(function(item) { + contentsJSON.images = platformLaunchStoryboardImages.map(function (item) { var newItem = { idiom: item.idiom, scale: item.scale }; // Xcode doesn't want any size class property if the class is "any" - // If our size class is "com", Xcode wants "compact". + // If our size class is "com", Xcode wants "compact". if (item.width !== CDV_ANY_SIZE_CLASS) { newItem['width-class'] = IMAGESET_COMPACT_SIZE_CLASS; } @@ -681,7 +694,7 @@ function getLaunchStoryboardContentsJSON(splashScreens, launchStoryboardImagesDi newItem['height-class'] = IMAGESET_COMPACT_SIZE_CLASS; } - // Xcode doesn't want a filename property if there's no image for these traits + // Xcode doesn't want a filename property if there's no image for these traits if (item.filename) { newItem.filename = item.filename; } @@ -692,14 +705,14 @@ function getLaunchStoryboardContentsJSON(splashScreens, launchStoryboardImagesDi /** * Determines if the project's build settings may need to be updated for launch storyboard support - * + * */ -function checkIfBuildSettingsNeedUpdatedForLaunchStoryboard(platformConfig, infoPlist) { +function checkIfBuildSettingsNeedUpdatedForLaunchStoryboard (platformConfig, infoPlist) { var hasLaunchStoryboardImages = platformHasLaunchStoryboardImages(platformConfig); var hasLegacyLaunchImages = platformHasLegacyLaunchImages(platformConfig); var currentLaunchStoryboard = infoPlist[UI_LAUNCH_STORYBOARD_NAME]; - if (hasLaunchStoryboardImages && currentLaunchStoryboard == CDV_LAUNCH_STORYBOARD_NAME && !hasLegacyLaunchImages) { + if (hasLaunchStoryboardImages && currentLaunchStoryboard === CDV_LAUNCH_STORYBOARD_NAME && !hasLegacyLaunchImages) { // don't need legacy launch images if we are using our launch storyboard // so we do need to update the project file events.emit('verbose', 'Need to update build settings because project is using our launch storyboard.'); @@ -714,12 +727,12 @@ function checkIfBuildSettingsNeedUpdatedForLaunchStoryboard(platformConfig, info return false; } -function updateBuildSettingsForLaunchStoryboard(proj, platformConfig, infoPlist) { +function updateBuildSettingsForLaunchStoryboard (proj, platformConfig, infoPlist) { var hasLaunchStoryboardImages = platformHasLaunchStoryboardImages(platformConfig); var hasLegacyLaunchImages = platformHasLegacyLaunchImages(platformConfig); var currentLaunchStoryboard = infoPlist[UI_LAUNCH_STORYBOARD_NAME]; - if (hasLaunchStoryboardImages && currentLaunchStoryboard == CDV_LAUNCH_STORYBOARD_NAME && !hasLegacyLaunchImages) { + if (hasLaunchStoryboardImages && currentLaunchStoryboard === CDV_LAUNCH_STORYBOARD_NAME && !hasLegacyLaunchImages) { // don't need legacy launch images if we are using our launch storyboard events.emit('verbose', 'Removed ' + LAUNCHIMAGE_BUILD_SETTING + ' because project is using our launch storyboard.'); proj.removeBuildProperty(LAUNCHIMAGE_BUILD_SETTING); @@ -732,7 +745,7 @@ function updateBuildSettingsForLaunchStoryboard(proj, platformConfig, infoPlist) } } -function splashScreensHaveLaunchStoryboardImages(contentsJSON) { +function splashScreensHaveLaunchStoryboardImages (contentsJSON) { /* do we have any launch images do we have for our launch storyboard? * Again, for old Node versions, the below code is equivalent to this: * return !!contentsJSON.images.find(function (item) { @@ -744,13 +757,13 @@ function splashScreensHaveLaunchStoryboardImages(contentsJSON) { }, undefined); } -function platformHasLaunchStoryboardImages(platformConfig) { +function platformHasLaunchStoryboardImages (platformConfig) { var splashScreens = platformConfig.getSplashScreens('ios'); - var contentsJSON = getLaunchStoryboardContentsJSON(splashScreens, ''); // note: we don't need a file path here; we're just counting + var contentsJSON = getLaunchStoryboardContentsJSON(splashScreens, ''); // note: we don't need a file path here; we're just counting return splashScreensHaveLaunchStoryboardImages(contentsJSON); } -function platformHasLegacyLaunchImages(platformConfig) { +function platformHasLegacyLaunchImages (platformConfig) { var splashScreens = platformConfig.getSplashScreens('ios'); return !!splashScreens.reduce(function (p, c) { return (c.width !== undefined || c.height !== undefined) ? c : p; @@ -760,13 +773,13 @@ function platformHasLegacyLaunchImages(platformConfig) { /** * Updates the project's plist based upon our launch storyboard images. If there are no images, then we should * fall back to the regular launch images that might be supplied (that is, our app will be scaled on an iPad Pro), - * and if there are some images, we need to alter the UILaunchStoryboardName property to point to + * and if there are some images, we need to alter the UILaunchStoryboardName property to point to * CDVLaunchScreen. - * + * * There's some logic here to avoid overwriting changes the user might have made to their plist if they are using * their own launch storyboard. */ -function updateProjectPlistForLaunchStoryboard(platformConfig, infoPlist) { +function updateProjectPlistForLaunchStoryboard (platformConfig, infoPlist) { var currentLaunchStoryboard = infoPlist[UI_LAUNCH_STORYBOARD_NAME]; events.emit('verbose', 'Current launch storyboard ' + currentLaunchStoryboard); @@ -794,11 +807,11 @@ function updateProjectPlistForLaunchStoryboard(platformConfig, infoPlist) { /** * Returns the directory for the Launch Storyboard image set, if image sets are being used. If they aren't * being used, returns null. - * + * * @param {string} projectRoot The project's root directory * @param {string} platformProjDir The platform's project directory */ -function getLaunchStoryboardImagesDir(projectRoot, platformProjDir) { +function getLaunchStoryboardImagesDir (projectRoot, platformProjDir) { var launchStoryboardImagesDir; var xcassetsExists = folderExists(path.join(projectRoot, platformProjDir, 'Images.xcassets/')); @@ -814,11 +827,11 @@ function getLaunchStoryboardImagesDir(projectRoot, platformProjDir) { /** * Update the images for the Launch Storyboard and updates the image set's contents.json file appropriately. - * + * * @param {Object} cordovaProject The cordova project * @param {Object} locations A dictionary containing useful location paths */ -function updateLaunchStoryboardImages(cordovaProject, locations) { +function updateLaunchStoryboardImages (cordovaProject, locations) { var splashScreens = cordovaProject.projectConfig.getSplashScreens('ios'); var platformProjDir = path.relative(cordovaProject.root, locations.xcodeCordovaProj); var launchStoryboardImagesDir = getLaunchStoryboardImagesDir(cordovaProject.root, platformProjDir); @@ -830,10 +843,10 @@ function updateLaunchStoryboardImages(cordovaProject, locations) { events.emit('verbose', 'Updating launch storyboard images at ' + launchStoryboardImagesDir); FileUpdater.updatePaths( resourceMap, { rootDir: cordovaProject.root }, logFileOp); - + events.emit('verbose', 'Updating Storyboard image set contents.json'); fs.writeFileSync(path.join(cordovaProject.root, launchStoryboardImagesDir, 'Contents.json'), - JSON.stringify(contentsJSON, null, 2)); + JSON.stringify(contentsJSON, null, 2)); } } @@ -842,10 +855,10 @@ function updateLaunchStoryboardImages(cordovaProject, locations) { * file appropriately. * * @param {string} projectRoot Path to the project root - * @param {Object} projectConfig The project's config.xml + * @param {Object} projectConfig The project's config.xml * @param {Object} locations A dictionary containing useful location paths */ -function cleanLaunchStoryboardImages(projectRoot, projectConfig, locations) { +function cleanLaunchStoryboardImages (projectRoot, projectConfig, locations) { var splashScreens = projectConfig.getSplashScreens('ios'); var platformProjDir = path.relative(projectRoot, locations.xcodeCordovaProj); var launchStoryboardImagesDir = getLaunchStoryboardImagesDir(projectRoot, platformProjDir); @@ -863,13 +876,13 @@ function cleanLaunchStoryboardImages(projectRoot, projectConfig, locations) { resourceMap, { rootDir: projectRoot, all: true }, logFileOp); // delete filename from contents.json - contentsJSON.images.forEach(function(image) { + contentsJSON.images.forEach(function (image) { image.filename = undefined; }); events.emit('verbose', 'Updating Storyboard image set contents.json'); fs.writeFileSync(path.join(projectRoot, launchStoryboardImagesDir, 'Contents.json'), - JSON.stringify(contentsJSON, null, 2)); + JSON.stringify(contentsJSON, null, 2)); } } @@ -882,7 +895,7 @@ function cleanLaunchStoryboardImages(projectRoot, projectConfig, locations) { * @return {String} Global/platform-specific orientation in lower-case * (or empty string if both are undefined). */ -function getOrientationValue(platformConfig) { +function getOrientationValue (platformConfig) { var ORIENTATION_DEFAULT = 'default'; @@ -894,7 +907,7 @@ function getOrientationValue(platformConfig) { orientation = orientation.toLowerCase(); // Check if the given global orientation is supported - if (['default', 'portrait','landscape', 'all'].indexOf(orientation) >= 0) { + if (['default', 'portrait', 'landscape', 'all'].indexOf(orientation) >= 0) { return orientation; } @@ -920,48 +933,49 @@ function getOrientationValue(platformConfig) { // (Apple already enforces this in ATS) NSAllowsArbitraryLoadsInWebContent, // boolean (default: false) NSAllowsLocalNetworking, // boolean (default: false) - NSAllowsArbitraryLoadsInMedia, // boolean (default:false) + NSAllowsArbitraryLoadsForMedia, // boolean (default:false) + } */ -function processAccessAndAllowNavigationEntries(config) { +function processAccessAndAllowNavigationEntries (config) { var accesses = config.getAccesses(); var allow_navigations = config.getAllowNavigations(); return allow_navigations - // we concat allow_navigations and accesses, after processing accesses - .concat(accesses.map(function(obj) { - // map accesses to a common key interface using 'href', not origin - obj.href = obj.origin; - delete obj.origin; - return obj; - })) - // we reduce the array to an object with all the entries processed (key is Hostname) - .reduce(function(previousReturn, currentElement) { - var options = { - minimum_tls_version : currentElement.minimum_tls_version, - requires_forward_secrecy : currentElement.requires_forward_secrecy, - requires_certificate_transparency : currentElement.requires_certificate_transparency, - allows_arbitrary_loads_in_media : currentElement.allows_arbitrary_loads_in_media, - allows_arbitrary_loads_in_web_content : currentElement.allows_arbitrary_loads_in_web_content, - allows_local_networking : currentElement.allows_local_networking - }; - var obj = parseWhitelistUrlForATS(currentElement.href, options); + // we concat allow_navigations and accesses, after processing accesses + .concat(accesses.map(function (obj) { + // map accesses to a common key interface using 'href', not origin + obj.href = obj.origin; + delete obj.origin; + return obj; + })) + // we reduce the array to an object with all the entries processed (key is Hostname) + .reduce(function (previousReturn, currentElement) { + var options = { + minimum_tls_version: currentElement.minimum_tls_version, + requires_forward_secrecy: currentElement.requires_forward_secrecy, + requires_certificate_transparency: currentElement.requires_certificate_transparency, + allows_arbitrary_loads_for_media: currentElement.allows_arbitrary_loads_in_media || currentElement.allows_arbitrary_loads_for_media, + allows_arbitrary_loads_in_web_content: currentElement.allows_arbitrary_loads_in_web_content, + allows_local_networking: currentElement.allows_local_networking + }; + var obj = parseWhitelistUrlForATS(currentElement.href, options); - if (obj) { - // we 'union' duplicate entries - var item = previousReturn[obj.Hostname]; - if (!item) { - item = {}; - } - for(var o in obj) { - if (obj.hasOwnProperty(o)) { - item[o] = obj[o]; + if (obj) { + // we 'union' duplicate entries + var item = previousReturn[obj.Hostname]; + if (!item) { + item = {}; + } + for (var o in obj) { + if (obj.hasOwnProperty(o)) { + item[o] = obj[o]; + } } + previousReturn[obj.Hostname] = item; } - previousReturn[obj.Hostname] = item; - } - return previousReturn; - }, {}); + return previousReturn; + }, {}); } /* @@ -979,12 +993,12 @@ function processAccessAndAllowNavigationEntries(config) { // (Apple already enforces this in ATS) NSAllowsArbitraryLoadsInWebContent, // boolean (default: false) NSAllowsLocalNetworking, // boolean (default: false) - NSAllowsArbitraryLoadsInMedia, // boolean (default:false) + NSAllowsArbitraryLoadsForMedia, // boolean (default:false) } null is returned if the URL cannot be parsed, or is to be skipped for ATS. */ -function parseWhitelistUrlForATS(url, options) { +function parseWhitelistUrlForATS (url, options) { var href = URL.parse(url); var retObj = {}; retObj.Hostname = href.hostname; @@ -1000,9 +1014,9 @@ function parseWhitelistUrlForATS(url, options) { retObj.NSAllowsArbitraryLoadsInWebContent = true; } - val = (options.allows_arbitrary_loads_in_media === 'true'); - if (options.allows_arbitrary_loads_in_media && val) { // default is false - retObj.NSAllowsArbitraryLoadsInMedia = true; + val = (options.allows_arbitrary_loads_for_media === 'true'); + if (options.allows_arbitrary_loads_for_media && val) { // default is false + retObj.NSAllowsArbitraryLoadsForMedia = true; } val = (options.allows_local_networking === 'true'); @@ -1049,25 +1063,23 @@ function parseWhitelistUrlForATS(url, options) { // if the scheme is HTTP, we set NSExceptionAllowsInsecureHTTPLoads to YES. Default is NO if (href.protocol === 'http:') { retObj.NSExceptionAllowsInsecureHTTPLoads = true; - } - else if (!href.protocol && href.pathname.indexOf('*:/') === 0) { // wilcard in protocol + } else if (!href.protocol && href.pathname.indexOf('*:/') === 0) { // wilcard in protocol retObj.NSExceptionAllowsInsecureHTTPLoads = true; } return retObj; } - /* App Transport Security (ATS) writer from <access> and <allow-navigation> tags in config.xml */ -function writeATSEntries(config) { - var pObj = processAccessAndAllowNavigationEntries(config); +function writeATSEntries (config) { + var pObj = processAccessAndAllowNavigationEntries(config); var ats = {}; - for(var hostname in pObj) { + for (var hostname in pObj) { if (pObj.hasOwnProperty(hostname)) { var entry = pObj[hostname]; @@ -1082,19 +1094,19 @@ function writeATSEntries(config) { if (entry.NSAllowsArbitraryLoadsInWebContent) { ats['NSAllowsArbitraryLoadsInWebContent'] = true; } - if (entry.NSAllowsArbitraryLoadsInMedia) { - ats['NSAllowsArbitraryLoadsInMedia'] = true; + if (entry.NSAllowsArbitraryLoadsForMedia) { + ats['NSAllowsArbitraryLoadsForMedia'] = true; } if (entry.NSAllowsLocalNetworking) { ats['NSAllowsLocalNetworking'] = true; } - + continue; } var exceptionDomain = {}; - for(var key in entry) { + for (var key in entry) { if (entry.hasOwnProperty(key) && key !== 'Hostname') { exceptionDomain[key] = entry[key]; } @@ -1111,7 +1123,7 @@ function writeATSEntries(config) { return ats; } -function folderExists(folderPath) { +function folderExists (folderPath) { try { var stat = fs.statSync(folderPath); return stat && stat.isDirectory(); @@ -1122,14 +1134,14 @@ function folderExists(folderPath) { // Construct a default value for CFBundleVersion as the version with any // -rclabel stripped=. -function default_CFBundleVersion(version) { +function default_CFBundleVersion (version) { return version.split('-')[0]; } // Converts cordova specific representation of target device to XCode value -function parseTargetDevicePreference(value) { +function parseTargetDevicePreference (value) { if (!value) return null; - var map = { 'universal': '"1,2"', 'handset': '"1"', 'tablet': '"2"'}; + var map = {'universal': '"1,2"', 'handset': '"1"', 'tablet': '"2"'}; if (map[value.toLowerCase()]) { return map[value.toLowerCase()]; } diff --git a/StoneIsland/platforms/ios/cordova/lib/projectFile.js b/StoneIsland/platforms/ios/cordova/lib/projectFile.js index aab38639..8a3f7e51 100755 --- a/StoneIsland/platforms/ios/cordova/lib/projectFile.js +++ b/StoneIsland/platforms/ios/cordova/lib/projectFile.js @@ -17,8 +17,6 @@ under the License. */ -/*jshint node: true*/ - var xcode = require('xcode'); var plist = require('plist'); var _ = require('underscore'); @@ -31,7 +29,7 @@ var CordovaError = require('cordova-common').CordovaError; var cachedProjectFiles = {}; -function parseProjectFile(locations) { +function parseProjectFile (locations) { var project_dir = locations.root; var pbxPath = locations.pbxproj; @@ -62,24 +60,24 @@ function parseProjectFile(locations) { var resourcesDir = path.resolve(xcode_dir, 'Resources'); cachedProjectFiles[project_dir] = { - plugins_dir:pluginsDir, - resources_dir:resourcesDir, - xcode:xcodeproj, - xcode_path:xcode_dir, + plugins_dir: pluginsDir, + resources_dir: resourcesDir, + xcode: xcodeproj, + xcode_path: xcode_dir, pbx: pbxPath, projectDir: project_dir, platformWww: path.join(project_dir, 'platform_www'), www: path.join(project_dir, 'www'), write: function () { fs.writeFileSync(pbxPath, xcodeproj.writeSync()); - if (Object.keys(this.frameworks).length === 0){ + if (Object.keys(this.frameworks).length === 0) { // If there is no framework references remain in the project, just remove this file shell.rm('-rf', frameworks_file); return; } fs.writeFileSync(frameworks_file, JSON.stringify(this.frameworks, null, 4)); }, - getPackageName: function() { + getPackageName: function () { return plist.parse(fs.readFileSync(plist_file, 'utf8')).CFBundleIdentifier; }, getInstaller: function (name) { @@ -93,7 +91,7 @@ function parseProjectFile(locations) { return cachedProjectFiles[project_dir]; } -function purgeProjectFileCache(project_dir) { +function purgeProjectFileCache (project_dir) { delete cachedProjectFiles[project_dir]; } @@ -115,7 +113,7 @@ xcode.project.prototype.addToPbxEmbedFrameworksBuildPhase = function (file) { xcode.project.prototype.removeFromPbxEmbedFrameworksBuildPhase = function (file) { var sources = this.pbxEmbedFrameworksBuildPhaseObj(file.target); if (sources) { - sources.files = _.reject(sources.files, function(file){ + sources.files = _.reject(sources.files, function (file) { return file.comment === longComment(file); }); } @@ -124,13 +122,13 @@ xcode.project.prototype.removeFromPbxEmbedFrameworksBuildPhase = function (file) // special handlers to add frameworks to the 'Embed Frameworks' build phase, needed for custom frameworks // see CB-9517. should probably be moved to node-xcode. var util = require('util'); -function pbxBuildPhaseObj(file) { +function pbxBuildPhaseObj (file) { var obj = Object.create(null); obj.value = file.uuid; obj.comment = longComment(file); return obj; } -function longComment(file) { +function longComment (file) { return util.format('%s in %s', file.basename, file.group); } diff --git a/StoneIsland/platforms/ios/cordova/lib/run.js b/StoneIsland/platforms/ios/cordova/lib/run.js index 0caadf06..3a6246e1 100755 --- a/StoneIsland/platforms/ios/cordova/lib/run.js +++ b/StoneIsland/platforms/ios/cordova/lib/run.js @@ -17,14 +17,12 @@ under the License. */ -/*jshint node: true*/ - -var Q = require('q'), - path = require('path'), - iossim = require('ios-sim'), - build = require('./build'), - spawn = require('./spawn'), - check_reqs = require('./check_reqs'); +var Q = require('q'); +var path = require('path'); +var iossim = require('ios-sim'); +var build = require('./build'); +var spawn = require('./spawn'); +var check_reqs = require('./check_reqs'); var events = require('cordova-common').events; @@ -40,109 +38,117 @@ module.exports.run = function (runOptions) { // support for CB-8168 `cordova/run --list` if (runOptions.list) { - if (runOptions.device) return listDevices(); - if (runOptions.emulator) return listEmulators(); + if (runOptions.device) return module.exports.listDevices(); + if (runOptions.emulator) return module.exports.listEmulators(); // if no --device or --emulator flag is specified, list both devices and emulators - return listDevices().then(function () { - return listEmulators(); + return module.exports.listDevices().then(function () { + return module.exports.listEmulators(); }); } var useDevice = !!runOptions.device; return require('./list-devices').run() - .then(function (devices) { - if (devices.length > 0 && !(runOptions.emulator)) { - useDevice = true; - // we also explicitly set device flag in options as we pass - // those parameters to other api (build as an example) - runOptions.device = true; - return check_reqs.check_ios_deploy(); - } - }).then(function () { - if (!runOptions.nobuild) { - return build.run(runOptions); - } else { - return Q.resolve(); - } - }).then(function () { - return build.findXCodeProjectIn(projectPath); - }).then(function (projectName) { - var appPath = path.join(projectPath, 'build', 'emulator', projectName + '.app'); - var buildOutputDir = path.join(projectPath, 'build', 'device'); + .then(function (devices) { + if (devices.length > 0 && !(runOptions.emulator)) { + useDevice = true; + // we also explicitly set device flag in options as we pass + // those parameters to other api (build as an example) + runOptions.device = true; + return check_reqs.check_ios_deploy(); + } + }).then(function () { + if (!runOptions.nobuild) { + return build.run(runOptions); + } else { + return Q.resolve(); + } + }).then(function () { + return build.findXCodeProjectIn(projectPath); + }).then(function (projectName) { + var appPath = path.join(projectPath, 'build', 'emulator', projectName + '.app'); + var buildOutputDir = path.join(projectPath, 'build', 'device'); - // select command to run and arguments depending whether - // we're running on device/emulator - if (useDevice) { - return checkDeviceConnected() - .then(function() { - // Unpack IPA - var ipafile = path.join(buildOutputDir, projectName + '.ipa'); + // select command to run and arguments depending whether + // we're running on device/emulator + if (useDevice) { + return module.exports.checkDeviceConnected() + .then(function () { + // Unpack IPA + var ipafile = path.join(buildOutputDir, projectName + '.ipa'); - // unpack the existing platform/ios/build/device/appname.ipa (zipfile), will create a Payload folder - return spawn('unzip', [ '-o', '-qq', ipafile ], buildOutputDir); - }) - .then(function() { - // Uncompress IPA (zip file) - var appFileInflated = path.join(buildOutputDir, 'Payload', projectName + '.app'); - var appFile = path.join(buildOutputDir, projectName + '.app'); - var payloadFolder = path.join(buildOutputDir, 'Payload'); + // unpack the existing platform/ios/build/device/appname.ipa (zipfile), will create a Payload folder + return spawn('unzip', [ '-o', '-qq', ipafile ], buildOutputDir); + }) + .then(function () { + // Uncompress IPA (zip file) + var appFileInflated = path.join(buildOutputDir, 'Payload', projectName + '.app'); + var appFile = path.join(buildOutputDir, projectName + '.app'); + var payloadFolder = path.join(buildOutputDir, 'Payload'); - // delete the existing platform/ios/build/device/appname.app - return spawn('rm', [ '-rf', appFile ], buildOutputDir) - .then(function() { - // move the platform/ios/build/device/Payload/appname.app to parent - return spawn('mv', [ '-f', appFileInflated, buildOutputDir ], buildOutputDir); + // delete the existing platform/ios/build/device/appname.app + return spawn('rm', [ '-rf', appFile ], buildOutputDir) + .then(function () { + // move the platform/ios/build/device/Payload/appname.app to parent + return spawn('mv', [ '-f', appFileInflated, buildOutputDir ], buildOutputDir); + }) + .then(function () { + // delete the platform/ios/build/device/Payload folder + return spawn('rm', [ '-rf', payloadFolder ], buildOutputDir); + }); }) - .then(function() { - // delete the platform/ios/build/device/Payload folder - return spawn('rm', [ '-rf', payloadFolder ], buildOutputDir); + .then(function () { + appPath = path.join(projectPath, 'build', 'device', projectName + '.app'); + var extraArgs = []; + if (runOptions.argv) { + // argv.slice(2) removes node and run.js, filterSupportedArgs removes the run.js args + extraArgs = module.exports.filterSupportedArgs(runOptions.argv.slice(2)); + } + return module.exports.deployToDevice(appPath, runOptions.target, extraArgs); + }, function () { + // if device connection check failed use emulator then + return module.exports.deployToSim(appPath, runOptions.target); }); - }) - .then(function() { - appPath = path.join(projectPath, 'build', 'device', projectName + '.app'); - var extraArgs = []; - if (runOptions.argv) { - // argv.slice(2) removes node and run.js, filterSupportedArgs removes the run.js args - extraArgs = filterSupportedArgs(runOptions.argv.slice(2)); - } - return deployToDevice(appPath, runOptions.target, extraArgs); - }, function () { - // if device connection check failed use emulator then - return deployToSim(appPath, runOptions.target); - }); - } else { - return deployToSim(appPath, runOptions.target); - } - }); + } else { + return module.exports.deployToSim(appPath, runOptions.target); + } + }); }; +module.exports.filterSupportedArgs = filterSupportedArgs; +module.exports.checkDeviceConnected = checkDeviceConnected; +module.exports.deployToDevice = deployToDevice; +module.exports.deployToSim = deployToSim; +module.exports.startSim = startSim; +module.exports.listDevices = listDevices; +module.exports.listEmulators = listEmulators; + /** * Filters the args array and removes supported args for the 'run' command. * * @return {Array} array with unsupported args for the 'run' command */ -function filterSupportedArgs(args) { - var filtered = []; - var sargs = ['--device', '--emulator', '--nobuild', '--list', '--target', '--debug', '--release']; - var re = new RegExp(sargs.join('|')); +function filterSupportedArgs (args) { + var filtered = []; + var sargs = ['--device', '--emulator', '--nobuild', '--list', '--target', '--debug', '--release']; + var re = new RegExp(sargs.join('|')); - args.forEach(function(element) { - // supported args not found, we add - // we do a regex search because --target can be "--target=XXX" - if (element.search(re) == -1) { - filtered.push(element); - } - }, this); + args.forEach(function (element) { + // supported args not found, we add + // we do a regex search because --target can be "--target=XXX" + if (element.search(re) === -1) { + filtered.push(element); + } + }, this); - return filtered; + return filtered; } /** * Checks if any iOS device is connected * @return {Promise} Fullfilled when any device is connected, rejected otherwise */ -function checkDeviceConnected() { +function checkDeviceConnected () { return spawn('ios-deploy', ['-c', '-t', '1']); } @@ -152,7 +158,7 @@ function checkDeviceConnected() { * @param {String} appPath Path to application package * @return {Promise} Resolves when deploy succeeds otherwise rejects */ -function deployToDevice(appPath, target, extraArgs) { +function deployToDevice (appPath, target, extraArgs) { // Deploying to device... if (target) { return spawn('ios-deploy', ['--justlaunch', '-d', '-b', appPath, '-i', target].concat(extraArgs)); @@ -167,51 +173,51 @@ function deployToDevice(appPath, target, extraArgs) { * @param {String} target Target device type * @return {Promise} Resolves when deploy succeeds otherwise rejects */ -function deployToSim(appPath, target) { +function deployToSim (appPath, target) { // Select target device for emulator. Default is 'iPhone-6' if (!target) { return require('./list-emulator-images').run() - .then(function (emulators) { - if (emulators.length > 0) { - target = emulators[0]; - } - emulators.forEach(function (emulator) { - if (emulator.indexOf('iPhone') === 0) { - target = emulator; + .then(function (emulators) { + if (emulators.length > 0) { + target = emulators[0]; } + emulators.forEach(function (emulator) { + if (emulator.indexOf('iPhone') === 0) { + target = emulator; + } + }); + events.emit('log', 'No target specified for emulator. Deploying to ' + target + ' simulator'); + return startSim(appPath, target); }); - events.emit('log','No target specified for emulator. Deploying to ' + target + ' simulator'); - return startSim(appPath, target); - }); } else { return startSim(appPath, target); } } -function startSim(appPath, target) { +function startSim (appPath, target) { var logPath = path.join(cordovaPath, 'console.log'); return iossim.launch(appPath, 'com.apple.CoreSimulator.SimDeviceType.' + target, logPath, '--exit'); } -function listDevices() { +function listDevices () { return require('./list-devices').run() - .then(function (devices) { - events.emit('log','Available iOS Devices:'); - devices.forEach(function (device) { - events.emit('log','\t' + device); + .then(function (devices) { + events.emit('log', 'Available iOS Devices:'); + devices.forEach(function (device) { + events.emit('log', '\t' + device); + }); }); - }); } -function listEmulators() { +function listEmulators () { return require('./list-emulator-images').run() - .then(function (emulators) { - events.emit('log','Available iOS Simulators:'); - emulators.forEach(function (emulator) { - events.emit('log','\t' + emulator); + .then(function (emulators) { + events.emit('log', 'Available iOS Simulators:'); + emulators.forEach(function (emulator) { + events.emit('log', '\t' + emulator); + }); }); - }); } module.exports.help = function () { @@ -230,7 +236,7 @@ module.exports.help = function () { console.log('Examples:'); console.log(' run'); console.log(' run --device'); - console.log(' run --emulator --target=\"iPhone-6-Plus\"'); + console.log(' run --emulator --target=\"iPhone-6-Plus\"'); /* eslint no-useless-escape : 0 */ console.log(' run --device --release'); console.log(' run --emulator --debug'); console.log(''); diff --git a/StoneIsland/platforms/ios/cordova/lib/spawn.js b/StoneIsland/platforms/ios/cordova/lib/spawn.js index 2162b9c7..b5a56852 100755 --- a/StoneIsland/platforms/ios/cordova/lib/spawn.js +++ b/StoneIsland/platforms/ios/cordova/lib/spawn.js @@ -17,32 +17,30 @@ under the License. */ -/*jshint node: true*/ - -var Q = require('q'), - proc = require('child_process'); +var Q = require('q'); +var proc = require('child_process'); /** - * Run specified command with arguments + * Run specified command with arguments * @param {String} cmd Command * @param {Array} args Array of arguments that should be passed to command * @param {String} opt_cwd Working directory for command * @param {String} opt_verbosity Verbosity level for command stdout output, "verbose" by default * @return {Promise} Promise either fullfilled or rejected with error code */ -module.exports = function(cmd, args, opt_cwd) { +module.exports = function (cmd, args, opt_cwd) { var d = Q.defer(); try { var child = proc.spawn(cmd, args, {cwd: opt_cwd, stdio: 'inherit'}); - child.on('exit', function(code) { + child.on('exit', function (code) { if (code) { d.reject('Error code ' + code + ' for command: ' + cmd + ' with args: ' + args); } else { d.resolve(); } }); - } catch(e) { + } catch (e) { d.reject(e); } return d.promise; diff --git a/StoneIsland/platforms/ios/cordova/lib/versions.js b/StoneIsland/platforms/ios/cordova/lib/versions.js index da31d4fa..c6a41b83 100755 --- a/StoneIsland/platforms/ios/cordova/lib/versions.js +++ b/StoneIsland/platforms/ios/cordova/lib/versions.js @@ -19,53 +19,51 @@ under the License. */ -var child_process = require('child_process'), - Q = require('q'); +var child_process = require('child_process'); +var Q = require('q'); -exports.get_apple_ios_version = function() { +exports.get_apple_ios_version = function () { var d = Q.defer(); - child_process.exec('xcodebuild -showsdks', function(error, stdout, stderr) { + child_process.exec('xcodebuild -showsdks', function (error, stdout, stderr) { if (error) { d.reject(stderr); - } - else { + } else { d.resolve(stdout); } }); - return d.promise.then(function(output) { - var regex = /[0-9]*\.[0-9]*/, - versions = [], - regexIOS = /^iOS \d+/; + return d.promise.then(function (output) { + var regex = /[0-9]*\.[0-9]*/; + var versions = []; + var regexIOS = /^iOS \d+/; output = output.split('\n'); for (var i = 0; i < output.length; i++) { if (output[i].trim().match(regexIOS)) { versions[versions.length] = parseFloat(output[i].match(regex)[0]); - } + } } versions.sort(); console.log(versions[0]); return Q(); - }, function(stderr) { + }, function (stderr) { return Q.reject(stderr); }); }; -exports.get_apple_osx_version = function() { +exports.get_apple_osx_version = function () { var d = Q.defer(); - child_process.exec('xcodebuild -showsdks', function(error, stdout, stderr) { + child_process.exec('xcodebuild -showsdks', function (error, stdout, stderr) { if (error) { d.reject(stderr); - } - else { + } else { d.resolve(stdout); } }); - return d.promise.then(function(output) { - var regex = /[0-9]*\.[0-9]*/, - versions = [], - regexOSX = /^OS X \d+/; + return d.promise.then(function (output) { + var regex = /[0-9]*\.[0-9]*/; + var versions = []; + var regexOSX = /^OS X \d+/; output = output.split('\n'); for (var i = 0; i < output.length; i++) { if (output[i].trim().match(regexOSX)) { @@ -75,14 +73,14 @@ exports.get_apple_osx_version = function() { versions.sort(); console.log(versions[0]); return Q(); - }, function(stderr) { + }, function (stderr) { return Q.reject(stderr); }); }; -exports.get_apple_xcode_version = function() { +exports.get_apple_xcode_version = function () { var d = Q.defer(); - child_process.exec('xcodebuild -version', function(error, stdout, stderr) { + child_process.exec('xcodebuild -version', function (error, stdout, stderr) { var versionMatch = /Xcode (.*)/.exec(stdout); if (error || !versionMatch) { d.reject(stderr); @@ -98,9 +96,9 @@ exports.get_apple_xcode_version = function() { * @return {Promise} Promise that either resolved with ios-deploy version * or rejected in case of error */ -exports.get_ios_deploy_version = function() { +exports.get_ios_deploy_version = function () { var d = Q.defer(); - child_process.exec('ios-deploy --version', function(error, stdout, stderr) { + child_process.exec('ios-deploy --version', function (error, stdout, stderr) { if (error) { d.reject(stderr); } else { @@ -115,9 +113,9 @@ exports.get_ios_deploy_version = function() { * @return {Promise} Promise that either resolved with pod version * or rejected in case of error */ -exports.get_cocoapods_version = function() { +exports.get_cocoapods_version = function () { var d = Q.defer(); - child_process.exec('pod --version', function(error, stdout, stderr) { + child_process.exec('pod --version', function (error, stdout, stderr) { if (error) { d.reject(stderr); } else { @@ -132,9 +130,9 @@ exports.get_cocoapods_version = function() { * @return {Promise} Promise that either resolved with ios-sim version * or rejected in case of error */ -exports.get_ios_sim_version = function() { +exports.get_ios_sim_version = function () { var d = Q.defer(); - child_process.exec('ios-sim --version', function(error, stdout, stderr) { + child_process.exec('ios-sim --version', function (error, stdout, stderr) { if (error) { d.reject(stderr); } else { @@ -152,11 +150,11 @@ exports.get_ios_sim_version = function() { */ exports.get_tool_version = function (toolName) { switch (toolName) { - case 'xcodebuild': return exports.get_apple_xcode_version(); - case 'ios-sim': return exports.get_ios_sim_version(); - case 'ios-deploy': return exports.get_ios_deploy_version(); - case 'pod': return exports.get_cocoapods_version(); - default: return Q.reject(toolName + ' is not valid tool name. Valid names are: \'xcodebuild\', \'ios-sim\', \'ios-deploy\', and \'pod\''); + case 'xcodebuild': return exports.get_apple_xcode_version(); + case 'ios-sim': return exports.get_ios_sim_version(); + case 'ios-deploy': return exports.get_ios_deploy_version(); + case 'pod': return exports.get_cocoapods_version(); + default: return Q.reject(toolName + ' is not valid tool name. Valid names are: \'xcodebuild\', \'ios-sim\', \'ios-deploy\', and \'pod\''); } }; |
