createIcons: function (callback) { this.logger.info(__('Creating favicon and Apple touch icons')); var file = this.projectResDir + '/' + this.tiapp.icon; if (!/\.(png|jpg|gif)$/.test(file) || !afs.exists(file)) { file = this.projectResDir + '/mobileweb/appicon.png'; } if (afs.exists(file)) { appc.image.resize(file, [ { file: this.buildDir + '/favicon.png', width: 16, height: 16 }, { file: this.buildDir + '/apple-touch-icon-precomposed.png', width: 57, height: 57 }, { file: this.buildDir + '/apple-touch-icon-57x57-precomposed.png', width: 57, height: 57 }, { file: this.buildDir + '/apple-touch-icon-72x72-precomposed.png', width: 72, height: 72 }, { file: this.buildDir + '/apple-touch-icon-114x114-precomposed.png', width: 114, height: 114 }, ], function (err, stdout, stderr) { if (err) { this.logger.error(__('Failed to create icons')); stderr.toString().split('\n').forEach(function (line) { this.logger.error(line); }); process.exit(1); } callback(); }); } else { callback(); } },
createIcons: function (callback) { this.logger.info(__('Creating favicon and Apple touch icons')); var file = path.join(this.projectResDir, this.tiapp.icon); if (!/\.(png|jpg|gif)$/.test(file) || !afs.exists(file)) { file = path.join(this.projectResDir, 'mobileweb', 'appicon.png'); } if (afs.exists(file)) { afs.copyFileSync(file, this.buildDir, { logger: this.logger.debug }); appc.image.resize(file, [ { file: this.buildDir + '/favicon.ico', width: 16, height: 16 }, { file: this.buildDir + '/apple-touch-icon-precomposed.png', width: 57, height: 57 }, { file: this.buildDir + '/apple-touch-icon-57x57-precomposed.png', width: 57, height: 57 }, { file: this.buildDir + '/apple-touch-icon-72x72-precomposed.png', width: 72, height: 72 }, { file: this.buildDir + '/apple-touch-icon-114x114-precomposed.png', width: 114, height: 114 }, ], function (err, stdout, stderr) { if (err) { this.logger.error(__('Failed to create icons')); stdout && stdout.toString().split('\n').forEach(function (line) { line && this.logger.error(line.replace(/^\[ERROR\]/i, '').trim()); }, this); stderr && stderr.toString().split('\n').forEach(function (line) { line && this.logger.error(line.replace(/^\[ERROR\]/i, '').trim()); }, this); this.logger.log(''); process.exit(1); } callback(); }.bind(this), this.logger); } else { callback(); } },
MobileWebBuilder.prototype.createIcons = function createIcons(next) { this.logger.info(__('Creating favicon and Apple touch icons')); var file = path.join(this.projectResDir, this.tiapp.icon); if (!/\.(png|jpg|gif)$/.test(file) || !fs.existsSync(file)) { file = path.join(this.projectResDir, 'mobileweb', 'appicon.png'); } if (!fs.existsSync(file)) { return next(); } afs.copyFileSync(file, this.buildDir, { logger: this.logger.debug }); var params = [ { file: path.join(this.buildDir, 'favicon.ico'), width: 16, height: 16 }, { file: path.join(this.buildDir, 'apple-touch-icon-precomposed.png'), width: 57, height: 57 }, { file: path.join(this.buildDir, 'apple-touch-icon-57x57-precomposed.png'), width: 57, height: 57 }, { file: path.join(this.buildDir, 'apple-touch-icon-72x72-precomposed.png'), width: 72, height: 72 }, { file: path.join(this.buildDir, 'apple-touch-icon-114x114-precomposed.png'), width: 114, height: 114 }, { file: path.join(this.buildDir, 'appicon144.png'), width: 144, height: 144 } ]; appc.image.resize(file, params, function (err, stdout, stderr) { if (err) { this.logger.error(__('Failed to create icons')); stdout && stdout.toString().split('\n').forEach(function (line) { line && this.logger.error(line.replace(/^\[ERROR\]/i, '').trim()); }, this); stderr && stderr.toString().split('\n').forEach(function (line) { line && this.logger.error(line.replace(/^\[ERROR\]/i, '').trim()); }, this); this.logger.log(''); process.exit(1); } next(); }.bind(this), this.logger); };
cli.on('build.mobileweb.createIcons', function (builder, callback) { if (builder.target !== 'wp8' && builder.target !== 'winstore') return callback(); logger.info(__('Creating favicon')); var buildDir = builder.buildDir, iconFilename = /\.(png|jpg|gif)$/.test(builder.tiapp.icon) ? builder.tiapp.icon : 'appicon.png', file = path.join(builder.projectResDir, 'mobileweb', iconFilename), resizeImages = []; if (!fs.existsSync(file)) { // try in the root file = path.join(builder.projectResDir, iconFilename); } // if they don't have a appicon, copy it from the sdk if (!fs.existsSync(file)) { file = path.join(builder.platformPath, 'templates', 'app', 'default', 'Resources', 'mobileweb', 'appicon.png'); } // copy the appicon.png appc.fs.copyFileSync(file, buildDir, { logger: logger.debug }); function copyIcon(filename, width, height) { var file = path.join(builder.projectResDir, 'mobileweb', filename); if (!fs.existsSync(file)) { file = path.join(builder.projectResDir, filename); } if (fs.existsSync(file)) { appc.fs.copyFileSync(file, buildDir, { logger: logger.debug }); } else { resizeImages.push({ file: path.join(buildDir, filename).replace(/\.ico$/, '.png'), width: width, height: height }); } } copyIcon('favicon.png', 16, 16); // if there are no images to resize, just return if (!resizeImages.length) return callback(); appc.image.resize(file, resizeImages, function (err, stdout, stderr) { if (err) { logger.error(__('Failed to create icons')); stdout && stdout.toString().split('\n').forEach(function (line) { line && logger.error(line.replace(/^\[ERROR\]/i, '').trim()); }); stderr && stderr.toString().split('\n').forEach(function (line) { line && logger.error(line.replace(/^\[ERROR\]/i, '').trim()); }); logger.log(''); process.exit(1); } // rename the favicon fs.renameSync(path.join(buildDir, 'favicon.png'), path.join(buildDir, 'favicon.ico')); callback(); }, logger); });
Builder.prototype.generateAppIcons = function generateAppIcons(icons, callback) { var defaultIcon, contents, requiredMissing = icons.filter(function (icon) { return icon.required; }).length, size = null, minRequiredSize = null, minSize = null, i, icon, rename = [], printMissing = function (logger, all) { icons.forEach(function (icon) { if (all || size === null || icon.width > size.width) { logger(' ' + __('%s - size: %sx%s', icon.description, icon.width, icon.height ) ); } }); }, fail = function () { this.logger.error(__('Unable to create missing icons:')); printMissing(this.logger.error); callback(true); }.bind(this), iconLabels; if (this.defaultIcons.length > 2) { var labels = this.defaultIcons.map(function (icon) { return '"' + path.basename(icon) + '"'; }), last = labels.pop(); iconLabels = labels.join(', ') + ', or ' + last; } else { iconLabels = this.defaultIcons.map(function (icon) { return '"' + path.basename(icon) + '"'; }).join(' or '); } this.defaultIcons.some(function (icon) { if (fs.existsSync(icon)) { defaultIcon = icon; return true; } }); if (!defaultIcon) { if (requiredMissing === 0) { this.logger.warn(__n('There is a missing app icon, but it is not required', 'There are missing app icons, but they are not required', icons.length)); this.logger.warn(__('You can either create the missing icons below or create an image named %s in the root of your project', iconLabels)); this.logger.warn(__('If the DefaultIcon.png image is present, the build will use it to generate all missing icons')); this.logger.warn(__('It is highly recommended that the DefaultIcon.png be 1024x1024')); printMissing(this.logger.warn); return callback(); } this.logger.error(__n('There is a missing required app icon', 'There are missing required app icons', icons.length)); this.logger.error(__('You must either create the missing icons below or create an image named %s in the root of your project', iconLabels)); this.logger.error(__('If the DefaultIcon.png image is present, the build will use it to generate all missing icons')); this.logger.error(__('It is highly recommended that the DefaultIcon.png be 1024x1024')); return fail(); } contents = fs.readFileSync(defaultIcon); size = appc.image.pngInfo(contents); if (size.width !== size.height) { this.logger.error(__('The %s is %sx%s, however the width and height must be equal', defaultIcon, size.width, size.height)); this.logger.error(__('It is highly recommended that the %s be 1024x1024', defaultIcon)); return fail(); } this.logger.debug(__('Found %s (%sx%s)', defaultIcon.cyan, size.width, size.height)); this.logger.info(__n( 'Missing %s app icon, generating missing icon', 'Missing %s app icons, generating missing icons', icons.length )); printMissing(this.logger.info, true); for (i = 0; i < icons.length; i++) { icon = icons[i]; if (icon.required) { if (minRequiredSize === null || icon.width > minRequiredSize) { minRequiredSize = icon.width; } } else if (icon.width > size.width) { // default icon isn't big enough, so we just skip this image this.logger.warn(__('%s (%sx%s) is not large enough to generate missing icon "%s" (%sx%s), skipping', defaultIcon, size.width, size.height, path.basename(icon.file), icon.width, icon.height)); icons.splice(i--, 1); continue; } if (minSize === null || icon.width > minSize) { minSize = icon.width; } if (!path.extname(icon.file)) { // the file doesn't have an extension, so we need to temporarily set // one so that the image resizer doesn't blow up rename.push({ from: icon.file + '.png', to: icon.file }); icon.file += '.png'; } } if (minRequiredSize !== null && size.width < minRequiredSize) { this.logger.error(__('The %s must be at least %sx%s', defaultIcon, minRequiredSize, minRequiredSize)); this.logger.error(__('It is highly recommended that the %s be 1024x1024', defaultIcon)); return fail(); } appc.image.resize(defaultIcon, icons, function (error, stdout, stderr) { if (error) { this.logger.error(error); this.logger.log(); process.exit(1); } rename.forEach(function (file) { fs.renameSync(file.from, file.to); }); callback(); }.bind(this), this.logger); };