summaryrefslogtreecommitdiff
path: root/StoneIsland/platforms/ios/cordova/lib/prepare.js
diff options
context:
space:
mode:
Diffstat (limited to 'StoneIsland/platforms/ios/cordova/lib/prepare.js')
-rw-r--r--[-rwxr-xr-x]StoneIsland/platforms/ios/cordova/lib/prepare.js863
1 files changed, 432 insertions, 431 deletions
diff --git a/StoneIsland/platforms/ios/cordova/lib/prepare.js b/StoneIsland/platforms/ios/cordova/lib/prepare.js
index 17bbfeb7..c98cb8f4 100755..100644
--- a/StoneIsland/platforms/ios/cordova/lib/prepare.js
+++ b/StoneIsland/platforms/ios/cordova/lib/prepare.js
@@ -18,53 +18,46 @@
*/
'use strict';
-var Q = require('q');
-var fs = require('fs');
-var path = require('path');
-var shell = require('shelljs');
-var xcode = require('xcode');
-var unorm = require('unorm');
-var plist = require('plist');
-var URL = require('url');
-var events = require('cordova-common').events;
-var xmlHelpers = require('cordova-common').xmlHelpers;
-var ConfigParser = require('cordova-common').ConfigParser;
-var CordovaError = require('cordova-common').CordovaError;
-var PlatformJson = require('cordova-common').PlatformJson;
-var PlatformMunger = require('cordova-common').ConfigChanges.PlatformMunger;
-var PluginInfoProvider = require('cordova-common').PluginInfoProvider;
-var FileUpdater = require('cordova-common').FileUpdater;
-var projectFile = require('./projectFile');
+
+const fs = require('fs-extra');
+const path = require('path');
+const unorm = require('unorm');
+const plist = require('plist');
+const URL = require('url');
+const events = require('cordova-common').events;
+const xmlHelpers = require('cordova-common').xmlHelpers;
+const ConfigParser = require('cordova-common').ConfigParser;
+const CordovaError = require('cordova-common').CordovaError;
+const PlatformJson = require('cordova-common').PlatformJson;
+const PlatformMunger = require('cordova-common').ConfigChanges.PlatformMunger;
+const PluginInfoProvider = require('cordova-common').PluginInfoProvider;
+const FileUpdater = require('cordova-common').FileUpdater;
+const projectFile = require('./projectFile');
// launch storyboard and related constants
-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';
+const IMAGESET_COMPACT_SIZE_CLASS = 'compact';
+const CDV_ANY_SIZE_CLASS = 'any';
module.exports.prepare = function (cordovaProject, options) {
- var self = this;
-
- var platformJson = PlatformJson.load(this.locations.root, 'ios');
- var munger = new PlatformMunger('ios', this.locations.root, platformJson, new PluginInfoProvider());
+ const platformJson = PlatformJson.load(this.locations.root, 'ios');
+ const munger = new PlatformMunger('ios', this.locations.root, platformJson, new PluginInfoProvider());
this._config = updateConfigFile(cordovaProject.projectConfig, munger, this.locations);
// 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);
+ return updateWww(cordovaProject, this.locations)
+ // update project according to config.xml changes.
+ .then(() => updateProject(this._config, this.locations))
+ .then(() => {
+ updateIcons(cordovaProject, this.locations);
+ updateLaunchStoryboardImages(cordovaProject, this.locations);
+ updateBackgroundColor(cordovaProject, this.locations);
+ updateFileResources(cordovaProject, this.locations);
})
- .then(function () {
- updateIcons(cordovaProject, self.locations);
- updateSplashScreens(cordovaProject, self.locations);
- updateLaunchStoryboardImages(cordovaProject, self.locations);
- updateFileResources(cordovaProject, self.locations);
+ .then(() => {
+ alertDeprecatedPreference(this._config);
})
- .then(function () {
+ .then(() => {
events.emit('verbose', 'Prepared iOS project successfully');
});
};
@@ -74,22 +67,21 @@ module.exports.clean = function (options) {
// been called from the platform shell script rather than the CLI. Check for the
// noPrepare option passed in by the non-CLI clean script. If that's present, or if
// there's no config.xml found at the project root, then don't clean prepared files.
- var projectRoot = path.resolve(this.root, '../..');
- var projectConfigFile = path.join(projectRoot, 'config.xml');
+ const projectRoot = path.resolve(this.root, '../..');
+ const projectConfigFile = path.join(projectRoot, 'config.xml');
if ((options && options.noPrepare) || !fs.existsSync(projectConfigFile) ||
!fs.existsSync(this.locations.configXml)) {
- return Q();
+ return Promise.resolve();
}
- var projectConfig = new ConfigParser(this.locations.configXml);
+ const projectConfig = new ConfigParser(this.locations.configXml);
- var self = this;
- return Q().then(function () {
- cleanWww(projectRoot, self.locations);
- cleanIcons(projectRoot, projectConfig, self.locations);
- cleanSplashScreens(projectRoot, projectConfig, self.locations);
- cleanLaunchStoryboardImages(projectRoot, projectConfig, self.locations);
- cleanFileResources(projectRoot, projectConfig, self.locations);
+ return Promise.resolve().then(() => {
+ cleanWww(projectRoot, this.locations);
+ cleanIcons(projectRoot, projectConfig, this.locations);
+ cleanLaunchStoryboardImages(projectRoot, projectConfig, this.locations);
+ cleanBackgroundColor(projectRoot, projectConfig, this.locations);
+ cleanFileResources(projectRoot, projectConfig, this.locations);
});
};
@@ -108,11 +100,11 @@ module.exports.clean = function (options) {
* configuration is already dumped to appropriate config.xml file.
*/
function updateConfigFile (sourceConfig, configMunger, locations) {
- events.emit('verbose', 'Generating platform-specific config.xml from defaults for iOS at ' + locations.configXml);
+ 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
// Overwrite platform config.xml with defaults.xml.
- shell.cp('-f', locations.defaultConfigXml, locations.configXml);
+ fs.copySync(locations.defaultConfigXml, locations.configXml);
// Then apply config changes from global munge to all config files
// in project (including project's config)
@@ -120,7 +112,7 @@ function updateConfigFile (sourceConfig, configMunger, locations) {
events.emit('verbose', 'Merging project\'s config.xml into platform-specific iOS config.xml');
// Merge changes from app's config.xml into platform's one
- var config = new ConfigParser(locations.configXml);
+ const config = new ConfigParser(locations.configXml);
xmlHelpers.mergeXml(sourceConfig.doc.getroot(),
config.doc.getroot(), 'ios', /* clobber= */true);
@@ -132,7 +124,7 @@ function updateConfigFile (sourceConfig, configMunger, locations) {
* Logs all file operations via the verbose event stream, indented.
*/
function logFileOp (message) {
- events.emit('verbose', ' ' + message);
+ events.emit('verbose', ` ${message}`);
}
/**
@@ -145,31 +137,33 @@ function logFileOp (message) {
* paths for www files.
*/
function updateWww (cordovaProject, destinations) {
- var sourceDirs = [
+ const sourceDirs = [
path.relative(cordovaProject.root, cordovaProject.locations.www),
path.relative(cordovaProject.root, destinations.platformWww)
];
// If project contains 'merges' for our platform, use them as another overrides
- var merges_path = path.join(cordovaProject.root, 'merges', 'ios');
+ const merges_path = path.join(cordovaProject.root, 'merges', 'ios');
if (fs.existsSync(merges_path)) {
events.emit('verbose', 'Found "merges/ios" folder. Copying its contents into the iOS project.');
sourceDirs.push(path.join('merges', 'ios'));
}
- var targetDir = path.relative(cordovaProject.root, destinations.www);
+ const targetDir = path.relative(cordovaProject.root, destinations.www);
events.emit(
- 'verbose', 'Merging and updating files from [' + sourceDirs.join(', ') + '] to ' + targetDir);
+ 'verbose', `Merging and updating files from [${sourceDirs.join(', ')}] to ${targetDir}`);
FileUpdater.mergeAndUpdateDir(
sourceDirs, targetDir, { rootDir: cordovaProject.root }, logFileOp);
+
+ return Promise.resolve();
}
/**
* Cleans all files from the platform 'www' directory.
*/
function cleanWww (projectRoot, locations) {
- var targetDir = path.relative(projectRoot, locations.www);
- events.emit('verbose', 'Cleaning ' + targetDir);
+ const targetDir = path.relative(projectRoot, locations.www);
+ events.emit('verbose', `Cleaning ${targetDir}`);
// No source paths are specified, so mergeAndUpdateDir() will clear the target directory.
FileUpdater.mergeAndUpdateDir(
@@ -184,169 +178,176 @@ function cleanWww (projectRoot, locations) {
* @param {Object} locations A map of locations for this platform (In/Out)
*/
function updateProject (platformConfig, locations) {
-
// CB-6992 it is necessary to normalize characters
// because node and shell scripts handles unicode symbols differently
// We need to normalize the name to NFD form since iOS uses NFD unicode form
- var name = unorm.nfd(platformConfig.name());
- var pkg = platformConfig.getAttribute('ios-CFBundleIdentifier') || platformConfig.packageName();
- var version = platformConfig.version();
- var displayName = platformConfig.shortName && platformConfig.shortName();
+ const name = unorm.nfd(platformConfig.name());
+ const version = platformConfig.version();
+ const displayName = platformConfig.shortName && platformConfig.shortName();
- var originalName = path.basename(locations.xcodeCordovaProj);
+ const originalName = path.basename(locations.xcodeCordovaProj);
// Update package id (bundle id)
- var plistFile = path.join(locations.xcodeCordovaProj, originalName + '-Info.plist');
- var infoPlist = plist.parse(fs.readFileSync(plistFile, 'utf8'));
- infoPlist['CFBundleIdentifier'] = pkg;
+ const plistFile = path.join(locations.xcodeCordovaProj, `${originalName}-Info.plist`);
+ const infoPlist = plist.parse(fs.readFileSync(plistFile, 'utf8'));
// Update version (bundle version)
- infoPlist['CFBundleShortVersionString'] = version;
- var CFBundleVersion = platformConfig.getAttribute('ios-CFBundleVersion') || default_CFBundleVersion(version);
- infoPlist['CFBundleVersion'] = CFBundleVersion;
+ infoPlist.CFBundleShortVersionString = version;
+ const CFBundleVersion = platformConfig.getAttribute('ios-CFBundleVersion') || default_CFBundleVersion(version);
+ infoPlist.CFBundleVersion = CFBundleVersion;
if (platformConfig.getAttribute('defaultlocale')) {
- infoPlist['CFBundleDevelopmentRegion'] = platformConfig.getAttribute('defaultlocale');
+ infoPlist.CFBundleDevelopmentRegion = platformConfig.getAttribute('defaultlocale');
}
if (displayName) {
- infoPlist['CFBundleDisplayName'] = displayName;
+ infoPlist.CFBundleDisplayName = displayName;
}
// replace Info.plist ATS entries according to <access> and <allow-navigation> config.xml entries
- var ats = writeATSEntries(platformConfig);
+ const ats = writeATSEntries(platformConfig);
if (Object.keys(ats).length > 0) {
- infoPlist['NSAppTransportSecurity'] = ats;
+ infoPlist.NSAppTransportSecurity = ats;
} else {
- delete infoPlist['NSAppTransportSecurity'];
+ delete infoPlist.NSAppTransportSecurity;
}
handleOrientationSettings(platformConfig, infoPlist);
- updateProjectPlistForLaunchStoryboard(platformConfig, infoPlist);
- var info_contents = plist.build(infoPlist);
+ /* eslint-disable no-tabs */
+ // Write out the plist file with the same formatting as Xcode does
+ let info_contents = plist.build(infoPlist, { indent: '\t', offset: -1 });
+ /* eslint-enable no-tabs */
+
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);
+ events.emit('verbose', `Wrote out iOS Bundle Version "${version}" to ${plistFile}`);
- return handleBuildSettings(platformConfig, locations, infoPlist).then(function () {
+ return handleBuildSettings(platformConfig, locations, infoPlist).then(() => {
if (name === originalName) {
- events.emit('verbose', 'iOS Product Name has not changed (still "' + originalName + '")');
- return Q();
+ events.emit('verbose', `iOS Product Name has not changed (still "${originalName}")`);
+ return Promise.resolve();
} else { // CB-11712 <name> was changed, we don't support it'
- var errorString =
+ const 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' +
'\tcordova plugin save\n' +
'\tcordova platform rm ios\n' +
- '\tcordova platform add ios\n'
- ;
+ '\tcordova platform add ios\n';
- return Q.reject(new CordovaError(errorString));
+ return Promise.reject(new CordovaError(errorString));
}
});
}
function handleOrientationSettings (platformConfig, infoPlist) {
-
switch (getOrientationValue(platformConfig)) {
case 'portrait':
- infoPlist['UIInterfaceOrientation'] = [ 'UIInterfaceOrientationPortrait' ];
- infoPlist['UISupportedInterfaceOrientations'] = [ 'UIInterfaceOrientationPortrait', 'UIInterfaceOrientationPortraitUpsideDown' ];
- infoPlist['UISupportedInterfaceOrientations~ipad'] = [ 'UIInterfaceOrientationPortrait', 'UIInterfaceOrientationPortraitUpsideDown' ];
+ 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' ];
+ 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' ];
+ 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'];
+ infoPlist.UISupportedInterfaceOrientations = ['UIInterfaceOrientationPortrait', 'UIInterfaceOrientationLandscapeLeft', 'UIInterfaceOrientationLandscapeRight'];
+ infoPlist['UISupportedInterfaceOrientations~ipad'] = ['UIInterfaceOrientationPortrait', 'UIInterfaceOrientationPortraitUpsideDown', 'UIInterfaceOrientationLandscapeLeft', 'UIInterfaceOrientationLandscapeRight'];
+ delete infoPlist.UIInterfaceOrientation;
}
}
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);
+ const pkg = platformConfig.getAttribute('ios-CFBundleIdentifier') || platformConfig.packageName();
+ const targetDevice = parseTargetDevicePreference(platformConfig.getPreference('target-device', 'ios'));
+ const deploymentTarget = platformConfig.getPreference('deployment-target', 'ios');
+ const swiftVersion = platformConfig.getPreference('SwiftVersion', 'ios');
+
+ let project;
+
+ try {
+ project = projectFile.parse(locations);
+ } catch (err) {
+ return Promise.reject(new CordovaError(`Could not parse ${locations.pbxproj}: ${err}`));
+ }
+
+ const origPkg = project.xcode.getBuildProperty('PRODUCT_BUNDLE_IDENTIFIER', undefined, platformConfig.name());
// 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();
+ if (origPkg === pkg && !targetDevice && !deploymentTarget && !swiftVersion) {
+ return Promise.resolve();
}
- var proj = new xcode.project(locations.pbxproj); /* eslint new-cap : 0 */
-
- try {
- proj.parseSync();
- } catch (err) {
- return Q.reject(new CordovaError('Could not parse project.pbxproj: ' + err));
+ if (origPkg !== pkg) {
+ events.emit('verbose', `Set PRODUCT_BUNDLE_IDENTIFIER to ${pkg}.`);
+ project.xcode.updateBuildProperty('PRODUCT_BUNDLE_IDENTIFIER', pkg, null, platformConfig.name());
}
if (targetDevice) {
- events.emit('verbose', 'Set TARGETED_DEVICE_FAMILY to ' + targetDevice + '.');
- proj.updateBuildProperty('TARGETED_DEVICE_FAMILY', targetDevice);
+ events.emit('verbose', `Set TARGETED_DEVICE_FAMILY to ${targetDevice}.`);
+ project.xcode.updateBuildProperty('TARGETED_DEVICE_FAMILY', targetDevice);
}
if (deploymentTarget) {
- events.emit('verbose', 'Set IPHONEOS_DEPLOYMENT_TARGET to "' + deploymentTarget + '".');
- proj.updateBuildProperty('IPHONEOS_DEPLOYMENT_TARGET', deploymentTarget);
+ events.emit('verbose', `Set IPHONEOS_DEPLOYMENT_TARGET to "${deploymentTarget}".`);
+ project.xcode.updateBuildProperty('IPHONEOS_DEPLOYMENT_TARGET', deploymentTarget);
}
- updateBuildSettingsForLaunchStoryboard(proj, platformConfig, infoPlist);
+ if (swiftVersion) {
+ events.emit('verbose', `Set SwiftVersion to "${swiftVersion}".`);
+ project.xcode.updateBuildProperty('SWIFT_VERSION', swiftVersion);
+ }
- fs.writeFileSync(locations.pbxproj, proj.writeSync(), 'utf-8');
+ project.write();
- return Q();
+ return Promise.resolve();
}
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-small@3x.png', width: 87, height: 87},
- {dest: 'icon.png', width: 57, height: 57},
- {dest: 'icon@2x.png', width: 114, height: 114},
- {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}
+ const 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-40@2x.png', width: 80, height: 80 },
+ { 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-29.png', width: 29, height: 29 },
+ { dest: 'icon-29@2x.png', width: 58, height: 58 },
+ { dest: 'icon-29@3x.png', width: 87, height: 87 },
+ { dest: 'icon.png', width: 57, height: 57 },
+ { dest: 'icon@2x.png', width: 114, height: 114 },
+ { dest: 'icon-24@2x.png', width: 48, height: 48 },
+ { dest: 'icon-27.5@2x.png', width: 55, height: 55 },
+ { dest: 'icon-44@2x.png', width: 88, height: 88 },
+ { dest: 'icon-86@2x.png', width: 172, height: 172 },
+ { dest: 'icon-98@2x.png', width: 196, height: 196 }
];
- var pathMap = {};
- platformIcons.forEach(function (item) {
- var icon = icons.getBySize(item.width, item.height) || icons.getDefault();
+ const pathMap = {};
+ platformIcons.forEach(item => {
+ const icon = icons.getBySize(item.width, item.height) || icons.getDefault();
if (icon) {
- var target = path.join(iconsDir, item.dest);
+ const target = path.join(iconsDir, item.dest);
pathMap[target] = icon.src;
}
});
@@ -354,8 +355,8 @@ function mapIconResources (icons, iconsDir) {
}
function getIconsDir (projectRoot, platformProjDir) {
- var iconsDir;
- var xcassetsExists = folderExists(path.join(projectRoot, platformProjDir, 'Images.xcassets/'));
+ let iconsDir;
+ const xcassetsExists = folderExists(path.join(projectRoot, platformProjDir, 'Images.xcassets/'));
if (xcassetsExists) {
iconsDir = path.join(platformProjDir, 'Images.xcassets/AppIcon.appiconset/');
@@ -367,31 +368,31 @@ function getIconsDir (projectRoot, platformProjDir) {
}
function updateIcons (cordovaProject, locations) {
- var icons = cordovaProject.projectConfig.getIcons('ios');
+ const icons = cordovaProject.projectConfig.getIcons('ios');
if (icons.length === 0) {
events.emit('verbose', 'This app does not have icons defined');
return;
}
- var platformProjDir = path.relative(cordovaProject.root, locations.xcodeCordovaProj);
- var iconsDir = getIconsDir(cordovaProject.root, platformProjDir);
- var resourceMap = mapIconResources(icons, iconsDir);
- events.emit('verbose', 'Updating icons at ' + iconsDir);
+ const platformProjDir = path.relative(cordovaProject.root, locations.xcodeCordovaProj);
+ const iconsDir = getIconsDir(cordovaProject.root, platformProjDir);
+ const resourceMap = mapIconResources(icons, iconsDir);
+ events.emit('verbose', `Updating icons at ${iconsDir}`);
FileUpdater.updatePaths(
resourceMap, { rootDir: cordovaProject.root }, logFileOp);
}
function cleanIcons (projectRoot, projectConfig, locations) {
- var icons = projectConfig.getIcons('ios');
+ const icons = projectConfig.getIcons('ios');
if (icons.length > 0) {
- var platformProjDir = path.relative(projectRoot, locations.xcodeCordovaProj);
- var iconsDir = getIconsDir(projectRoot, platformProjDir);
- var resourceMap = mapIconResources(icons, iconsDir);
- Object.keys(resourceMap).forEach(function (targetIconPath) {
+ const platformProjDir = path.relative(projectRoot, locations.xcodeCordovaProj);
+ const iconsDir = getIconsDir(projectRoot, platformProjDir);
+ const resourceMap = mapIconResources(icons, iconsDir);
+ Object.keys(resourceMap).forEach(targetIconPath => {
resourceMap[targetIconPath] = null;
});
- events.emit('verbose', 'Cleaning icons at ' + iconsDir);
+ events.emit('verbose', `Cleaning icons at ${iconsDir}`);
// Source paths are removed from the map, so updatePaths() will delete the target files.
FileUpdater.updatePaths(
@@ -399,74 +400,120 @@ function cleanIcons (projectRoot, projectConfig, locations) {
}
}
-function mapSplashScreenResources (splashScreens, splashScreensDir) {
- var platformSplashScreens = [
- {dest: 'Default~iphone.png', width: 320, height: 480},
- {dest: 'Default@2x~iphone.png', width: 640, height: 960},
- {dest: 'Default-Portrait~ipad.png', width: 768, height: 1024},
- {dest: 'Default-Portrait@2x~ipad.png', width: 1536, height: 2048},
- {dest: 'Default-Landscape~ipad.png', width: 1024, height: 768},
- {dest: 'Default-Landscape@2x~ipad.png', width: 2048, height: 1536},
- {dest: 'Default-568h@2x~iphone.png', width: 640, height: 1136},
- {dest: 'Default-667h.png', width: 750, height: 1334},
- {dest: 'Default-736h.png', width: 1242, height: 2208},
- {dest: 'Default-Landscape-736h.png', width: 2208, height: 1242}
- ];
-
- var pathMap = {};
- platformSplashScreens.forEach(function (item) {
- var splash = splashScreens.getBySize(item.width, item.height);
- if (splash) {
- var target = path.join(splashScreensDir, item.dest);
- pathMap[target] = splash.src;
- }
- });
- return pathMap;
+/**
+ * Returns the directory for the BackgroundColor.colorset asset, or null if no
+ * xcassets exist.
+ *
+ * @param {string} projectRoot The project's root directory
+ * @param {string} platformProjDir The platform's project directory
+ */
+function getBackgroundColorDir (projectRoot, platformProjDir) {
+ if (folderExists(path.join(projectRoot, platformProjDir, 'Images.xcassets/'))) {
+ return path.join(platformProjDir, 'Images.xcassets', 'BackgroundColor.colorset');
+ } else {
+ return null;
+ }
}
-function getSplashScreensDir (projectRoot, platformProjDir) {
- var splashScreensDir;
- var xcassetsExists = folderExists(path.join(projectRoot, platformProjDir, 'Images.xcassets/'));
+function colorPreferenceToComponents (pref) {
+ if (!pref || !pref.match(/^(#[0-9A-F]{3}|(0x|#)([0-9A-F]{2})?[0-9A-F]{6})$/)) {
+ return {
+ platform: 'ios',
+ reference: 'systemBackgroundColor'
+ };
+ }
- if (xcassetsExists) {
- splashScreensDir = path.join(platformProjDir, 'Images.xcassets/LaunchImage.launchimage/');
- } else {
- splashScreensDir = path.join(platformProjDir, 'Resources/splash/');
+ let red = 'FF';
+ let green = 'FF';
+ let blue = 'FF';
+ let alpha = 1.0;
+
+ if (pref[0] === '#' && pref.length === 4) {
+ red = pref[1] + pref[1];
+ green = pref[2] + pref[2];
+ blue = pref[3] + pref[3];
}
- return splashScreensDir;
-}
+ if (pref.length >= 7 && (pref[0] === '#' || pref.substring(0, 2) === '0x')) {
+ let offset = pref[0] === '#' ? 1 : 2;
-function updateSplashScreens (cordovaProject, locations) {
- var splashScreens = cordovaProject.projectConfig.getSplashScreens('ios');
+ if (pref.substring(offset).length === 8) {
+ alpha = parseInt(pref.substring(offset, offset + 2), 16) / 255.0;
+ offset += 2;
+ }
- if (splashScreens.length === 0) {
- events.emit('verbose', 'This app does not have splash screens defined');
- return;
+ red = pref.substring(offset, offset + 2);
+ green = pref.substring(offset + 2, offset + 4);
+ blue = pref.substring(offset + 4, offset + 6);
}
- var platformProjDir = path.relative(cordovaProject.root, locations.xcodeCordovaProj);
- var splashScreensDir = getSplashScreensDir(cordovaProject.root, platformProjDir);
- var resourceMap = mapSplashScreenResources(splashScreens, splashScreensDir);
- events.emit('verbose', 'Updating splash screens at ' + splashScreensDir);
- FileUpdater.updatePaths(
- resourceMap, { rootDir: cordovaProject.root }, logFileOp);
+ return {
+ 'color-space': 'srgb',
+ components: {
+ red: '0x' + red,
+ green: '0x' + green,
+ blue: '0x' + blue,
+ alpha: alpha.toFixed(3)
+ }
+ };
}
-function cleanSplashScreens (projectRoot, projectConfig, locations) {
- var splashScreens = projectConfig.getSplashScreens('ios');
- if (splashScreens.length > 0) {
- var platformProjDir = path.relative(projectRoot, locations.xcodeCordovaProj);
- var splashScreensDir = getSplashScreensDir(projectRoot, platformProjDir);
- var resourceMap = mapIconResources(splashScreens, splashScreensDir);
- Object.keys(resourceMap).forEach(function (targetSplashPath) {
- resourceMap[targetSplashPath] = null;
- });
- events.emit('verbose', 'Cleaning splash screens at ' + splashScreensDir);
+/**
+ * Update the background color Contents.json in xcassets.
+ *
+ * @param {Object} cordovaProject The cordova project
+ * @param {Object} locations A dictionary containing useful location paths
+ */
+function updateBackgroundColor (cordovaProject, locations) {
+ const pref = cordovaProject.projectConfig.getPreference('BackgroundColor', 'ios') || '';
- // Source paths are removed from the map, so updatePaths() will delete the target files.
- FileUpdater.updatePaths(
- resourceMap, { rootDir: projectRoot, all: true }, logFileOp);
+ const platformProjDir = path.relative(cordovaProject.root, locations.xcodeCordovaProj);
+ const backgroundColorDir = getBackgroundColorDir(cordovaProject.root, platformProjDir);
+
+ if (backgroundColorDir) {
+ const contentsJSON = {
+ colors: [{
+ idiom: 'universal',
+ color: colorPreferenceToComponents(pref)
+ }],
+ info: {
+ author: 'Xcode',
+ version: 1
+ }
+ };
+
+ events.emit('verbose', 'Updating Background Color color set Contents.json');
+ fs.writeFileSync(path.join(cordovaProject.root, backgroundColorDir, 'Contents.json'),
+ JSON.stringify(contentsJSON, null, 2));
+ }
+}
+
+/**
+ * Resets the background color Contents.json in xcassets to default.
+ *
+ * @param {string} projectRoot Path to the project root
+ * @param {Object} projectConfig The project's config.xml
+ * @param {Object} locations A dictionary containing useful location paths
+ */
+function cleanBackgroundColor (projectRoot, projectConfig, locations) {
+ const platformProjDir = path.relative(projectRoot, locations.xcodeCordovaProj);
+ const backgroundColorDir = getBackgroundColorDir(projectRoot, platformProjDir);
+
+ if (backgroundColorDir) {
+ const contentsJSON = {
+ colors: [{
+ idiom: 'universal',
+ color: colorPreferenceToComponents(null)
+ }],
+ info: {
+ author: 'Xcode',
+ version: 1
+ }
+ };
+
+ events.emit('verbose', 'Cleaning Background Color color set Contents.json');
+ fs.writeFileSync(path.join(projectRoot, backgroundColorDir, 'Contents.json'),
+ JSON.stringify(contentsJSON, null, 2));
}
}
@@ -482,9 +529,9 @@ function updateFileResources (cordovaProject, locations) {
return;
}
- let resourceMap = {};
- files.forEach(function (res) {
- let src = res.src;
+ const resourceMap = {};
+ files.forEach(res => {
+ const src = res.src;
let target = res.target;
if (!target) {
@@ -494,29 +541,75 @@ function updateFileResources (cordovaProject, locations) {
let targetPath = path.join(project.resources_dir, target);
targetPath = path.relative(cordovaProject.root, targetPath);
- project.xcode.addResourceFile(target);
+ if (!fs.existsSync(targetPath)) {
+ project.xcode.addResourceFile(target);
+ } else {
+ events.emit('warn', `Overwriting existing resource file at ${targetPath}`);
+ }
resourceMap[targetPath] = src;
});
- events.emit('verbose', 'Updating resource files at ' + platformDir);
+ events.emit('verbose', `Updating resource files at ${platformDir}`);
FileUpdater.updatePaths(
resourceMap, { rootDir: cordovaProject.root }, logFileOp);
project.write();
}
+function alertDeprecatedPreference (configParser) {
+ const deprecatedToNewPreferences = {
+ MediaPlaybackRequiresUserAction: {
+ newPreference: 'MediaTypesRequiringUserActionForPlayback',
+ isDeprecated: true
+ },
+ MediaPlaybackAllowsAirPlay: {
+ newPreference: 'AllowsAirPlayForMediaPlayback',
+ isDeprecated: false
+ }
+ };
+
+ Object.keys(deprecatedToNewPreferences).forEach(oldKey => {
+ if (configParser.getPreference(oldKey)) {
+ const isDeprecated = deprecatedToNewPreferences[oldKey].isDeprecated;
+ const verb = isDeprecated ? 'has been' : 'is being';
+ const newPreferenceKey = deprecatedToNewPreferences[oldKey].newPreference;
+
+ // Create the Log Message
+ const log = [`The preference name "${oldKey}" ${verb} deprecated.`];
+ if (newPreferenceKey) {
+ log.push(`It is recommended to replace this preference with "${newPreferenceKey}."`);
+ } else {
+ log.push('There is no replacement for this preference.');
+ }
+
+ /**
+ * If the preference has been deprecated, the usage of the old preference is no longer used.
+ * Therefore, the following line is not appended. It is added only if the old preference is still used.
+ * We are only keeping the top lines for deprecated items only for an additional major release when
+ * the pre-warning was not provided in a past major release due to a necessary quick deprecation.
+ * Typically caused by implementation nature or third-party requirement changes.
+ */
+ if (!isDeprecated) {
+ log.push('Please note that this preference will be removed in the near future.');
+ }
+
+ events.emit('warn', log.join(' '));
+ }
+ });
+}
+
function cleanFileResources (projectRoot, projectConfig, locations) {
const platformDir = path.relative(projectRoot, locations.root);
const files = projectConfig.getFileResources('ios', true);
if (files.length > 0) {
- events.emit('verbose', 'Cleaning resource files at ' + platformDir);
+ events.emit('verbose', `Cleaning resource files at ${platformDir}`);
const project = projectFile.parse(locations);
- var resourceMap = {};
- files.forEach(function (res) {
- let src = res.src;
+ const resourceMap = {};
+ files.forEach(res => {
+ const src = res.src;
let target = res.target;
if (!target) {
@@ -532,7 +625,7 @@ function cleanFileResources (projectRoot, projectConfig, locations) {
});
FileUpdater.updatePaths(
- resourceMap, {rootDir: projectRoot, all: true}, logFileOp);
+ resourceMap, { rootDir: projectRoot, all: true }, logFileOp);
project.write();
}
@@ -555,7 +648,8 @@ function cleanFileResources (projectRoot, projectConfig, locations) {
* height: 'any|com',
* filename: undefined|'Default@scale~idiom~widthheight.png',
* src: undefined|'path/to/original/matched/image/from/splash/screens.png',
- * target: undefined|'path/to/asset/library/Default@scale~idiom~widthheight.png'
+ * target: undefined|'path/to/asset/library/Default@scale~idiom~widthheight.png',
+ * appearence: undefined|'dark'|'light'
* }, ...
* ]
*
@@ -564,51 +658,54 @@ function cleanFileResources (projectRoot, projectConfig, locations) {
* @return {Array<Object>}
*/
function mapLaunchStoryboardContents (splashScreens, launchStoryboardImagesDir) {
- var platformLaunchStoryboardImages = [];
- var idioms = ['universal', 'ipad', 'iphone'];
- var scalesForIdiom = {
+ const platformLaunchStoryboardImages = [];
+ const idioms = ['universal', 'ipad', 'iphone'];
+ const scalesForIdiom = {
universal: ['1x', '2x', '3x'],
ipad: ['1x', '2x'],
iphone: ['1x', '2x', '3x']
};
- var sizes = ['com', 'any'];
+ const sizes = ['com', 'any'];
+ const appearences = ['', 'dark', 'light'];
- idioms.forEach(function (idiom) {
- scalesForIdiom[idiom].forEach(function (scale) {
- sizes.forEach(function (width) {
- sizes.forEach(function (height) {
- var item = {
- idiom: idiom,
- scale: scale,
- width: width,
- height: height
- };
+ idioms.forEach(idiom => {
+ scalesForIdiom[idiom].forEach(scale => {
+ sizes.forEach(width => {
+ sizes.forEach(height => {
+ appearences.forEach(appearence => {
+ const item = { idiom, scale, width, height };
- /* examples of the search pattern:
- * scale ~ idiom ~ width height
- * @2x ~ universal ~ any any
- * @3x ~ iphone ~ com any
- * @2x ~ ipad ~ com any
- */
- var searchPattern = '@' + scale + '~' + idiom + '~' + width + height;
+ if (appearence !== '') {
+ item.appearence = appearence;
+ }
- /* because old node versions don't have Array.find, the below is
- * functionally equivalent to this:
- * var launchStoryboardImage = splashScreens.find(function(item) {
- * return item.src.indexOf(searchPattern) >= 0;
- * });
- */
- var launchStoryboardImage = splashScreens.reduce(function (p, c) {
- return (c.src.indexOf(searchPattern) >= 0) ? c : p;
- }, undefined);
+ /* examples of the search pattern:
+ * scale ~ idiom ~ width height ~ appearence
+ * @2x ~ universal ~ any any
+ * @3x ~ iphone ~ com any ~ dark
+ * @2x ~ ipad ~ com any ~ light
+ */
+ const searchPattern = '@' + scale + '~' + idiom + '~' + width + height + (appearence ? '~' + appearence : '');
- if (launchStoryboardImage) {
- item.filename = 'Default' + searchPattern + '.png';
- item.src = launchStoryboardImage.src;
- item.target = path.join(launchStoryboardImagesDir, item.filename);
- }
+ /* because old node versions don't have Array.find, the below is
+ * functionally equivalent to this:
+ * var launchStoryboardImage = splashScreens.find(function(item) {
+ * return (item.src.indexOf(searchPattern) >= 0) ? (appearence !== '' ? true : ((item.src.indexOf(searchPattern + '~light') >= 0 || (item.src.indexOf(searchPattern + '~dark') >= 0)) ? false : true)) : false;
+ * });
+ */
+ const launchStoryboardImage = splashScreens.reduce(
+ (p, c) => (c.src.indexOf(searchPattern) >= 0) ? (appearence !== '' ? c : ((c.src.indexOf(searchPattern + '~light') >= 0 || (c.src.indexOf(searchPattern + '~dark') >= 0)) ? p : c)) : p,
+ undefined
+ );
- platformLaunchStoryboardImages.push(item);
+ if (launchStoryboardImage) {
+ item.filename = `Default${searchPattern}.png`;
+ item.src = launchStoryboardImage.src;
+ item.target = path.join(launchStoryboardImagesDir, item.filename);
+ }
+
+ platformLaunchStoryboardImages.push(item);
+ });
});
});
});
@@ -632,9 +729,9 @@ function mapLaunchStoryboardContents (splashScreens, launchStoryboardImagesDir)
* @return {Object}
*/
function mapLaunchStoryboardResources (splashScreens, launchStoryboardImagesDir) {
- var platformLaunchStoryboardImages = mapLaunchStoryboardContents(splashScreens, launchStoryboardImagesDir);
- var pathMap = {};
- platformLaunchStoryboardImages.forEach(function (item) {
+ const platformLaunchStoryboardImages = mapLaunchStoryboardContents(splashScreens, launchStoryboardImagesDir);
+ const pathMap = {};
+ platformLaunchStoryboardImages.forEach(item => {
if (item.target) {
pathMap[item.target] = item.src;
}
@@ -654,6 +751,7 @@ function mapLaunchStoryboardResources (splashScreens, launchStoryboardImagesDir)
* scale: '1x|2x|3x',
* width-class: undefined|'compact',
* height-class: undefined|'compact'
+ * ...
* }, ...
* ],
* info: {
@@ -670,17 +768,16 @@ function mapLaunchStoryboardResources (splashScreens, launchStoryboardImagesDir)
* @return {Object}
*/
function getLaunchStoryboardContentsJSON (splashScreens, launchStoryboardImagesDir) {
-
- var platformLaunchStoryboardImages = mapLaunchStoryboardContents(splashScreens, launchStoryboardImagesDir);
- var contentsJSON = {
+ const platformLaunchStoryboardImages = mapLaunchStoryboardContents(splashScreens, launchStoryboardImagesDir);
+ const contentsJSON = {
images: [],
info: {
author: 'Xcode',
version: 1
}
};
- contentsJSON.images = platformLaunchStoryboardImages.map(function (item) {
- var newItem = {
+ contentsJSON.images = platformLaunchStoryboardImages.map(item => {
+ const newItem = {
idiom: item.idiom,
scale: item.scale
};
@@ -694,6 +791,10 @@ function getLaunchStoryboardContentsJSON (splashScreens, launchStoryboardImagesD
newItem['height-class'] = IMAGESET_COMPACT_SIZE_CLASS;
}
+ if (item.appearence) {
+ newItem.appearances = [{ appearance: 'luminosity', value: item.appearence }];
+ }
+
// Xcode doesn't want a filename property if there's no image for these traits
if (item.filename) {
newItem.filename = item.filename;
@@ -704,107 +805,6 @@ function getLaunchStoryboardContentsJSON (splashScreens, launchStoryboardImagesD
}
/**
- * Determines if the project's build settings may need to be updated for launch storyboard support
- *
- */
-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) {
- // 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.');
- return true;
- } else if (hasLegacyLaunchImages && !currentLaunchStoryboard) {
- // we do need to ensure legacy launch images are used if there's no launch storyboard present
- // so we do need to update the project file
- events.emit('verbose', 'Need to update build settings because project is using legacy launch images and no storyboard.');
- return true;
- }
- events.emit('verbose', 'No need to update build settings for launch storyboard support.');
- return false;
-}
-
-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) {
- // 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);
- } else if (hasLegacyLaunchImages && !currentLaunchStoryboard) {
- // we do need to ensure legacy launch images are used if there's no launch storyboard present
- events.emit('verbose', 'Set ' + LAUNCHIMAGE_BUILD_SETTING + ' to ' + LAUNCHIMAGE_BUILD_SETTING_VALUE + ' because project is using legacy launch images and no storyboard.');
- proj.updateBuildProperty(LAUNCHIMAGE_BUILD_SETTING, LAUNCHIMAGE_BUILD_SETTING_VALUE);
- } else {
- events.emit('verbose', 'Did not update build settings for launch storyboard support.');
- }
-}
-
-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) {
- * return item.filename !== undefined;
- * });
- */
- return !!contentsJSON.images.reduce(function (p, c) {
- return (c.filename !== undefined) ? c : p;
- }, undefined);
-}
-
-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
- return splashScreensHaveLaunchStoryboardImages(contentsJSON);
-}
-
-function platformHasLegacyLaunchImages (platformConfig) {
- var splashScreens = platformConfig.getSplashScreens('ios');
- return !!splashScreens.reduce(function (p, c) {
- return (c.width !== undefined || c.height !== undefined) ? c : p;
- }, undefined);
-}
-
-/**
- * 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
- * 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) {
- var currentLaunchStoryboard = infoPlist[UI_LAUNCH_STORYBOARD_NAME];
- events.emit('verbose', 'Current launch storyboard ' + currentLaunchStoryboard);
-
- var hasLaunchStoryboardImages = platformHasLaunchStoryboardImages(platformConfig);
-
- if (hasLaunchStoryboardImages && !currentLaunchStoryboard) {
- // only change the launch storyboard if we have images to use AND the current value is blank
- // if it's not blank, we've either done this before, or the user has their own launch storyboard
- events.emit('verbose', 'Changing info plist to use our launch storyboard');
- infoPlist[UI_LAUNCH_STORYBOARD_NAME] = CDV_LAUNCH_STORYBOARD_NAME;
- return;
- }
-
- if (!hasLaunchStoryboardImages && currentLaunchStoryboard === CDV_LAUNCH_STORYBOARD_NAME) {
- // only revert to using the launch images if we have don't have any images for the launch storyboard
- // but only clear it if current launch storyboard is our storyboard; the user might be using their
- // own storyboard instead.
- events.emit('verbose', 'Changing info plist to use legacy launch images');
- delete infoPlist[UI_LAUNCH_STORYBOARD_NAME];
- return;
- }
- events.emit('verbose', 'Not changing launch storyboard setting in info plist.');
-}
-
-/**
* Returns the directory for the Launch Storyboard image set, if image sets are being used. If they aren't
* being used, returns null.
*
@@ -812,8 +812,8 @@ function updateProjectPlistForLaunchStoryboard (platformConfig, infoPlist) {
* @param {string} platformProjDir The platform's project directory
*/
function getLaunchStoryboardImagesDir (projectRoot, platformProjDir) {
- var launchStoryboardImagesDir;
- var xcassetsExists = folderExists(path.join(projectRoot, platformProjDir, 'Images.xcassets/'));
+ let launchStoryboardImagesDir;
+ const xcassetsExists = folderExists(path.join(projectRoot, platformProjDir, 'Images.xcassets/'));
if (xcassetsExists) {
launchStoryboardImagesDir = path.join(platformProjDir, 'Images.xcassets/LaunchStoryboard.imageset/');
@@ -832,15 +832,15 @@ function getLaunchStoryboardImagesDir (projectRoot, platformProjDir) {
* @param {Object} locations A dictionary containing useful location paths
*/
function updateLaunchStoryboardImages (cordovaProject, locations) {
- var splashScreens = cordovaProject.projectConfig.getSplashScreens('ios');
- var platformProjDir = path.relative(cordovaProject.root, locations.xcodeCordovaProj);
- var launchStoryboardImagesDir = getLaunchStoryboardImagesDir(cordovaProject.root, platformProjDir);
+ const splashScreens = cordovaProject.projectConfig.getSplashScreens('ios');
+ const platformProjDir = path.relative(cordovaProject.root, locations.xcodeCordovaProj);
+ const launchStoryboardImagesDir = getLaunchStoryboardImagesDir(cordovaProject.root, platformProjDir);
if (launchStoryboardImagesDir) {
- var resourceMap = mapLaunchStoryboardResources(splashScreens, launchStoryboardImagesDir);
- var contentsJSON = getLaunchStoryboardContentsJSON(splashScreens, launchStoryboardImagesDir);
+ const resourceMap = mapLaunchStoryboardResources(splashScreens, launchStoryboardImagesDir);
+ const contentsJSON = getLaunchStoryboardContentsJSON(splashScreens, launchStoryboardImagesDir);
- events.emit('verbose', 'Updating launch storyboard images at ' + launchStoryboardImagesDir);
+ events.emit('verbose', `Updating launch storyboard images at ${launchStoryboardImagesDir}`);
FileUpdater.updatePaths(
resourceMap, { rootDir: cordovaProject.root }, logFileOp);
@@ -859,24 +859,24 @@ function updateLaunchStoryboardImages (cordovaProject, locations) {
* @param {Object} locations A dictionary containing useful location paths
*/
function cleanLaunchStoryboardImages (projectRoot, projectConfig, locations) {
- var splashScreens = projectConfig.getSplashScreens('ios');
- var platformProjDir = path.relative(projectRoot, locations.xcodeCordovaProj);
- var launchStoryboardImagesDir = getLaunchStoryboardImagesDir(projectRoot, platformProjDir);
+ const splashScreens = projectConfig.getSplashScreens('ios');
+ const platformProjDir = path.relative(projectRoot, locations.xcodeCordovaProj);
+ const launchStoryboardImagesDir = getLaunchStoryboardImagesDir(projectRoot, platformProjDir);
if (launchStoryboardImagesDir) {
- var resourceMap = mapLaunchStoryboardResources(splashScreens, launchStoryboardImagesDir);
- var contentsJSON = getLaunchStoryboardContentsJSON(splashScreens, launchStoryboardImagesDir);
+ const resourceMap = mapLaunchStoryboardResources(splashScreens, launchStoryboardImagesDir);
+ const contentsJSON = getLaunchStoryboardContentsJSON(splashScreens, launchStoryboardImagesDir);
- Object.keys(resourceMap).forEach(function (targetPath) {
+ Object.keys(resourceMap).forEach(targetPath => {
resourceMap[targetPath] = null;
});
- events.emit('verbose', 'Cleaning storyboard image set at ' + launchStoryboardImagesDir);
+ events.emit('verbose', `Cleaning storyboard image set at ${launchStoryboardImagesDir}`);
// Source paths are removed from the map, so updatePaths() will delete the target files.
FileUpdater.updatePaths(
resourceMap, { rootDir: projectRoot, all: true }, logFileOp);
// delete filename from contents.json
- contentsJSON.images.forEach(function (image) {
+ contentsJSON.images.forEach(image => {
image.filename = undefined;
});
@@ -896,10 +896,9 @@ function cleanLaunchStoryboardImages (projectRoot, projectConfig, locations) {
* (or empty string if both are undefined).
*/
function getOrientationValue (platformConfig) {
+ const ORIENTATION_DEFAULT = 'default';
- var ORIENTATION_DEFAULT = 'default';
-
- var orientation = platformConfig.getPreference('orientation');
+ let orientation = platformConfig.getPreference('orientation');
if (!orientation) {
return '';
}
@@ -911,8 +910,7 @@ function getOrientationValue (platformConfig) {
return orientation;
}
- events.emit('warn', 'Unrecognized value for Orientation preference: ' + orientation +
- '. Defaulting to value: ' + ORIENTATION_DEFAULT + '.');
+ events.emit('warn', `Unrecognized value for Orientation preference: ${orientation}. Defaulting to value: ${ORIENTATION_DEFAULT}.`);
return ORIENTATION_DEFAULT;
}
@@ -938,20 +936,20 @@ function getOrientationValue (platformConfig) {
}
*/
function processAccessAndAllowNavigationEntries (config) {
- var accesses = config.getAccesses();
- var allow_navigations = config.getAllowNavigations();
+ const accesses = config.getAccesses();
+ const allow_navigations = config.getAllowNavigations();
return allow_navigations
- // we concat allow_navigations and accesses, after processing accesses
- .concat(accesses.map(function (obj) {
+ // we concat allow_navigations and accesses, after processing accesses
+ .concat(accesses.map(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 = {
+ .reduce((previousReturn, currentElement) => {
+ const options = {
minimum_tls_version: currentElement.minimum_tls_version,
requires_forward_secrecy: currentElement.requires_forward_secrecy,
requires_certificate_transparency: currentElement.requires_certificate_transparency,
@@ -959,16 +957,16 @@ function processAccessAndAllowNavigationEntries (config) {
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);
+ const obj = parseWhitelistUrlForATS(currentElement.href, options);
if (obj) {
// we 'union' duplicate entries
- var item = previousReturn[obj.Hostname];
+ let item = previousReturn[obj.Hostname];
if (!item) {
item = {};
}
- for (var o in obj) {
- if (obj.hasOwnProperty(o)) {
+ for (const o in obj) {
+ if (Object.prototype.hasOwnProperty.call(obj, o)) {
item[o] = obj[o];
}
}
@@ -999,15 +997,16 @@ function processAccessAndAllowNavigationEntries (config) {
null is returned if the URL cannot be parsed, or is to be skipped for ATS.
*/
function parseWhitelistUrlForATS (url, options) {
- var href = URL.parse(url);
- var retObj = {};
+ // @todo 'url.parse' was deprecated since v11.0.0. Use 'url.URL' constructor instead.
+ const href = URL.parse(url); // eslint-disable-line
+ const retObj = {};
retObj.Hostname = href.hostname;
// Guiding principle: we only set values in retObj if they are NOT the default
if (url === '*') {
retObj.Hostname = '*';
- var val;
+ let val;
val = (options.allows_arbitrary_loads_in_web_content === 'true');
if (options.allows_arbitrary_loads_in_web_content && val) { // default is false
@@ -1029,10 +1028,12 @@ function parseWhitelistUrlForATS (url, options) {
if (!retObj.Hostname) {
// check origin, if it allows subdomains (wildcard in hostname), we set NSIncludesSubdomains to YES. Default is NO
- var subdomain1 = '/*.'; // wildcard in hostname
- var subdomain2 = '*://*.'; // wildcard in hostname and protocol
- var subdomain3 = '*://'; // wildcard in protocol only
- if (href.pathname.indexOf(subdomain1) === 0) {
+ const subdomain1 = '/*.'; // wildcard in hostname
+ const subdomain2 = '*://*.'; // wildcard in hostname and protocol
+ const subdomain3 = '*://'; // wildcard in protocol only
+ if (!href.pathname) {
+ return null;
+ } else if (href.pathname.indexOf(subdomain1) === 0) {
retObj.NSIncludesSubdomains = true;
retObj.Hostname = href.pathname.substring(subdomain1.length);
} else if (href.pathname.indexOf(subdomain2) === 0) {
@@ -1050,12 +1051,12 @@ function parseWhitelistUrlForATS (url, options) {
retObj.NSExceptionMinimumTLSVersion = options.minimum_tls_version;
}
- var rfs = (options.requires_forward_secrecy === 'true');
+ const rfs = (options.requires_forward_secrecy === 'true');
if (options.requires_forward_secrecy && !rfs) { // default is true
retObj.NSExceptionRequiresForwardSecrecy = false;
}
- var rct = (options.requires_certificate_transparency === 'true');
+ const rct = (options.requires_certificate_transparency === 'true');
if (options.requires_certificate_transparency && rct) { // default is false
retObj.NSRequiresCertificateTransparency = true;
}
@@ -1075,48 +1076,48 @@ function parseWhitelistUrlForATS (url, options) {
in config.xml
*/
function writeATSEntries (config) {
- var pObj = processAccessAndAllowNavigationEntries(config);
+ const pObj = processAccessAndAllowNavigationEntries(config);
- var ats = {};
+ const ats = {};
- for (var hostname in pObj) {
- if (pObj.hasOwnProperty(hostname)) {
- var entry = pObj[hostname];
+ for (const hostname in pObj) {
+ if (Object.prototype.hasOwnProperty.call(pObj, hostname)) {
+ const entry = pObj[hostname];
// Guiding principle: we only set values if they are available
if (hostname === '*') {
// always write this, for iOS 9, since in iOS 10 it will be overriden if
// any of the other three keys are written
- ats['NSAllowsArbitraryLoads'] = true;
+ ats.NSAllowsArbitraryLoads = true;
// at least one of the overriding keys is present
if (entry.NSAllowsArbitraryLoadsInWebContent) {
- ats['NSAllowsArbitraryLoadsInWebContent'] = true;
+ ats.NSAllowsArbitraryLoadsInWebContent = true;
}
if (entry.NSAllowsArbitraryLoadsForMedia) {
- ats['NSAllowsArbitraryLoadsForMedia'] = true;
+ ats.NSAllowsArbitraryLoadsForMedia = true;
}
if (entry.NSAllowsLocalNetworking) {
- ats['NSAllowsLocalNetworking'] = true;
+ ats.NSAllowsLocalNetworking = true;
}
continue;
}
- var exceptionDomain = {};
+ const exceptionDomain = {};
- for (var key in entry) {
- if (entry.hasOwnProperty(key) && key !== 'Hostname') {
+ for (const key in entry) {
+ if (Object.prototype.hasOwnProperty.call(entry, key) && key !== 'Hostname') {
exceptionDomain[key] = entry[key];
}
}
- if (!ats['NSExceptionDomains']) {
- ats['NSExceptionDomains'] = {};
+ if (!ats.NSExceptionDomains) {
+ ats.NSExceptionDomains = {};
}
- ats['NSExceptionDomains'][hostname] = exceptionDomain;
+ ats.NSExceptionDomains[hostname] = exceptionDomain;
}
}
@@ -1125,7 +1126,7 @@ function writeATSEntries (config) {
function folderExists (folderPath) {
try {
- var stat = fs.statSync(folderPath);
+ const stat = fs.statSync(folderPath);
return stat && stat.isDirectory();
} catch (e) {
return false;
@@ -1141,10 +1142,10 @@ function default_CFBundleVersion (version) {
// Converts cordova specific representation of target device to XCode value
function parseTargetDevicePreference (value) {
if (!value) return null;
- var map = {'universal': '"1,2"', 'handset': '"1"', 'tablet': '"2"'};
+ const map = { universal: '"1,2"', handset: '"1"', tablet: '"2"' };
if (map[value.toLowerCase()]) {
return map[value.toLowerCase()];
}
- events.emit('warn', 'Unrecognized value for target-device preference: ' + value + '.');
+ events.emit('warn', `Unrecognized value for target-device preference: ${value}.`);
return null;
}