UNPKG

@ionic/cli-plugin-cordova

Version:

Ionic Cordova Plugin for Ionic CLI

225 lines (219 loc) 13.8 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); const path = require("path"); const chalk = require("chalk"); const cli_utils_1 = require("@ionic/cli-utils"); const resources_1 = require("../lib/resources"); const setup_1 = require("../lib/utils/setup"); const configXmlUtils_1 = require("../lib/utils/configXmlUtils"); const AVAILABLE_RESOURCE_TYPES = ['icon', 'splash']; let ResourcesCommand = class ResourcesCommand extends cli_utils_1.Command { preRun(inputs, options) { return __awaiter(this, void 0, void 0, function* () { const isLoggedIn = yield this.env.session.isLoggedIn(); if (!isLoggedIn) { this.env.log.warn(`You need to be logged into your Ionic account in order to run ${chalk.green(`ionic cordova resources`)}.\n`); yield cli_utils_1.promptToLogin(this.env); } }); } run(inputs, options) { return __awaiter(this, void 0, void 0, function* () { const [platform] = inputs; let resourceTypes = AVAILABLE_RESOURCE_TYPES.filter((type, index, array) => options[type]); resourceTypes = (resourceTypes.length) ? resourceTypes : AVAILABLE_RESOURCE_TYPES; const resourceDir = path.join(this.env.project.directory, 'resources'); this.env.tasks.next(`Collecting resource configuration and source images`); const configJson = yield configXmlUtils_1.parseConfigXmlToJson(this.env.project.directory); const config = yield this.env.config.load(); const resourceJsonStructure = yield resources_1.getResourceConfigJson(); this.env.log.debug(`resourceJsonStructure=${Object.keys(resourceJsonStructure).length}`); let platformDirContents = yield setup_1.getProjectPlatforms(this.env.project.directory); this.env.log.debug(`platformDirContents=${platformDirContents}`); if (platform && !platformDirContents.includes(platform)) { this.env.tasks.end(); const confirm = yield this.env.prompt({ message: `Platform ${chalk.green(platform)} is not installed! Would you like to install it?`, type: 'confirm', name: 'confirm', }); if (confirm) { yield setup_1.installPlatform(this.env, platform); platformDirContents = yield setup_1.getProjectPlatforms(this.env.project.directory); this.env.log.debug(`platformDirContents=${platformDirContents}`); } else { throw this.exit(`Platform ${chalk.green(platform)} not installed.`); } } const buildPlatforms = Object.keys(resourceJsonStructure).filter(p => platformDirContents.includes(p)); this.env.log.debug(`buildPlatforms=${buildPlatforms}`); if (buildPlatforms.length === 0) { this.env.tasks.end(); throw this.exit(`No platforms have been added. Please run: ${chalk.green('ionic cordova platform add')}`); } this.env.log.debug(`${chalk.green('getProjectPlatforms')} completed - length=${buildPlatforms.length}`); const orientation = configXmlUtils_1.getOrientationFromConfigJson(configJson) || 'default'; let imgResources = resources_1.flattenResourceJsonStructure(resourceJsonStructure) .filter((img) => orientation === 'default' || typeof img.orientation === 'undefined' || img.orientation === orientation) .filter((img) => buildPlatforms.includes(img.platform)) .filter((img) => resourceTypes.includes(img.resType)) .map((img) => (Object.assign({}, img, { dest: path.join(resourceDir, img.platform, img.resType, img.name) }))); if (platform) { imgResources = imgResources.filter((img) => img.platform === platform); } this.env.log.debug(`imgResources=${imgResources.length}`); const buildDirResponses = yield resources_1.createImgDestinationDirectories(imgResources); this.env.log.debug(`${chalk.green('createImgDestinationDirectories')} completed - length=${buildDirResponses.length}`); let srcImagesAvailable = []; try { srcImagesAvailable = yield resources_1.getSourceImages(buildPlatforms, resourceTypes, resourceDir); this.env.log.debug(`${chalk.green('getSourceImages')} completed - ${srcImagesAvailable.length}`); } catch (e) { } imgResources = imgResources.map((imageResource) => { const mostSpecificImageAvailable = resources_1.findMostSpecificImage(imageResource, srcImagesAvailable); return Object.assign({}, imageResource, { imageId: mostSpecificImageAvailable && mostSpecificImageAvailable.imageId ? mostSpecificImageAvailable.imageId : null }); }); const missingSrcImages = imgResources.filter((imageResource) => imageResource.imageId === null); if (missingSrcImages.length > 0) { const missingImageText = missingSrcImages .reduce((list, img) => { const str = `${img.platform}/${img.resType}`; if (!list.includes(str)) { list.push(str); } return list; }, []) .map(v => chalk.bold(v)) .join(', '); throw new cli_utils_1.FatalException(`Source image files were not found for the following platforms/types: ${missingImageText}\n\n` + `Please review ${chalk.green('--help')}`); } this.env.tasks.next(`Uploading source images to prepare for transformations`); let imageUploadResponses; const timeout = config.cliFlags.timeout; imageUploadResponses = yield resources_1.uploadSourceImages(srcImagesAvailable, timeout); this.env.log.debug(`${chalk.green('uploadSourceImages')} completed - responses=${JSON.stringify(imageUploadResponses, null, 2)}`); srcImagesAvailable = srcImagesAvailable.map((img, index) => { return Object.assign({}, img, { width: imageUploadResponses[index].Width, height: imageUploadResponses[index].Height, vector: imageUploadResponses[index].Vector }); }); const imagesTooLargeForSource = imgResources.filter((imageResource) => { const resourceSourceImage = srcImagesAvailable.find(srcImage => srcImage.imageId === imageResource.imageId); if (resourceSourceImage === undefined) { return true; } return !resourceSourceImage.vector && (imageResource.width > resourceSourceImage.width || imageResource.height > resourceSourceImage.height); }); imgResources = imgResources.filter(imageResource => { return !imagesTooLargeForSource.find(tooLargeForSourceImage => imageResource.name === tooLargeForSourceImage.name); }); this.env.tasks.next(`Generating platform resources`); let count = 0; const promiseList = imgResources.map((img, index) => __awaiter(this, void 0, void 0, function* () { yield resources_1.transformResourceImage(img, timeout); count += 1; this.env.tasks.updateMsg(`Generating platform resources: ${chalk.bold(`${count} / ${imgResources.length}`)} complete`); })); const generateImageResponses = yield Promise.all(promiseList); this.env.tasks.updateMsg(`Generating platform resources: ${chalk.bold(`${imgResources.length} / ${imgResources.length}`)} complete`); this.env.log.debug(`${chalk.green('generateResourceImage')} completed - responses=${JSON.stringify(generateImageResponses, null, 2)}`); this.env.tasks.next(`Modifying config.xml to add new image resources`); const imageResourcesForConfig = imgResources.reduce((rc, img) => { if (!rc[img.platform]) { rc[img.platform] = { [img.resType]: { images: [], nodeName: '', nodeAttributes: [] } }; } if (!rc[img.platform][img.resType]) { rc[img.platform][img.resType] = { images: [], nodeName: '', nodeAttributes: [] }; } rc[img.platform][img.resType].images.push({ name: img.name, width: img.width, height: img.height, density: img.density || null }); rc[img.platform][img.resType].nodeName = img.nodeName; rc[img.platform][img.resType].nodeAttributes = img.nodeAttributes; return rc; }, {}); const platformList = Object .keys(imageResourcesForConfig) .map(pn => pn); yield resources_1.addResourcesToConfigXml(this.env.project.directory, platformList, imageResourcesForConfig); this.env.tasks.end(); if (imagesTooLargeForSource.length > 0) { const imagesTooLargeForSourceMsg = imagesTooLargeForSource .map(imageResource => ` ${chalk.bold(imageResource.name)} ${imageResource.platform}/${imageResource.resType} needed ${imageResource.width}w x ${imageResource.height}h`) .concat((imagesTooLargeForSource.length > 0) ? `\nThe following images were not created because their source image was too small:` : []) .reverse(); this.env.log.info(imagesTooLargeForSourceMsg.join('\n')); } }); } }; ResourcesCommand = __decorate([ cli_utils_1.CommandMetadata({ name: 'resources', type: 'project', description: 'Automatically create icon and splash screen resources', longDescription: ` Ionic can automatically generate perfectly sized icons and splash screens from source images (${chalk.bold('.png')}, ${chalk.bold('.psd')}, or ${chalk.bold('.ai')}) for your Cordova platforms. The source image for icons should ideally be at least ${chalk.bold('1024x1024px')} and located at ${chalk.bold('resources/icon.png')}. The source image for splash screens should ideally be at least ${chalk.bold('2732x2732px')} and located at ${chalk.bold('resources/splash.png')}. If you used ${chalk.green('ionic start')}, there should already be default Ionic resources in the ${chalk.bold('resources/')} directory, which you can overwrite. You can also generate platform-specific icons and splash screens by placing them in the respective ${chalk.bold('resources/<platform>/')} directory. For example, to generate an icon for Android, place your image at ${chalk.bold('resources/android/icon.png')}. ${chalk.green('ionic cordova resources')} will automatically update your ${chalk.bold('config.xml')} to reflect the changes in the generated images, which Cordova then configures. Cordova reference documentation: - Icons: ${chalk.bold('https://cordova.apache.org/docs/en/latest/config_ref/images.html')} - Splash Screens: ${chalk.bold('https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-splashscreen/')} This command uses Ionic servers, so we require you to be logged into your free Ionic account. Use ${chalk.green('ionic login')} to login. `, exampleCommands: ['', 'ios', 'android'], inputs: [ { name: 'platform', description: `The platform for which you would like to generate resources (e.g. ${chalk.green('ios')}, ${chalk.green('android')})`, required: false, } ], options: [ { name: 'icon', description: 'Generate icon resources', type: Boolean, aliases: ['i'], }, { name: 'splash', description: 'Generate splash screen resources', type: Boolean, aliases: ['s'], } ] }) ], ResourcesCommand); exports.ResourcesCommand = ResourcesCommand;