diff --git a/README.md b/README.md index 2f0036d55..797787d35 100644 --- a/README.md +++ b/README.md @@ -145,10 +145,10 @@ Default value: `false` MAC ONLY: Use a `app.nw` folder instead of `ZIP` file, this significantly improves the startup speed of applications on `mac`, since no decompressing is needed. Builds on other platforms will still use `ZIP` files. #### options.macPlist -Type: `String` +Type: `String` or `Object` Default value: `false` -MAC ONLY: if you supply a string to a Plist file it will use it. Otherwise it will generate something usefull from your package.json +MAC ONLY: Pass a string containing the path to your own plist file. If a string isn't passed, a plist file will be generated from your package.json. Pass an object to overwrite or add properties to the generated plist file. #### options.winIco Type: `String` diff --git a/lib/index.js b/lib/index.js index 2830e69c7..623885cb8 100644 --- a/lib/index.js +++ b/lib/index.js @@ -378,13 +378,15 @@ NwBuilder.prototype.handleMacApp = function () { allDone.push(Utils.copyFile(self.options.macPlist, PlistPath)); } else { // Setup the Plst - var defaultPlist = { - appName: self.options.appName, - appVersion: self.options.appVersion, - copyright: self._appPkg.copyright || false - }; + var plistOptions = Utils.getPlistOptions( + { + name: self.options.appName, + version: self.options.appVersion, + copyright: self._appPkg.copyright || false + }, + self.options.macPlist + ); - var plistOptions = (self.options.macPlist ? _.defaults(self.options.macPlist, defaultPlist) : defaultPlist); allDone.push(Utils.editPlist(PlistPath, PlistPath, plistOptions)); } diff --git a/lib/utils.js b/lib/utils.js index 945635242..9ac32863e 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -1,11 +1,15 @@ var fs = require('fs-extra'); var path = require('path'); +var _ = require('lodash'); var Promise = require('bluebird'); var plist = require('plist'); var Glob = require('simple-glob'); var temp = require('temp'); var archiver = require('archiver'); +var readFile = Promise.promisify(fs.readFile); +var writeFile = Promise.promisify(fs.writeFile); + // Automatically track and cleanup files at exit temp.track(); @@ -136,41 +140,74 @@ module.exports = { }); }, - editPlist: function (plistInput, plistOutput, options) { - - return new Promise(function(resolve, reject) { - if(!options.appName || !options.appVersion) { - return reject('You have to set the appName and appVersion in the Plist options'); + getPlistOptions: function(parsedParams, custom) { + var obj = {}; + if(parsedParams.name !== undefined) { + obj.CFBundleName = parsedParams.name; + obj.CFBundleDisplayName = parsedParams.name; + } + if(parsedParams.version !== undefined) { + obj.CFBundleVersion = parsedParams.version; + obj.CFBundleShortVersionString = 'Version ' + parsedParams.version; + } + if(parsedParams.copyright !== undefined) { + obj.NSHumanReadableCopyright = parsedParams.copyright; + } + + return _.merge(obj, custom); + }, + editPlist: function(plistInput, plistOutput, options) { + options = options || {}; + + // Make sure all required properties are set + [ + 'CFBundleName', + 'CFBundleDisplayName', + 'CFBundleVersion', + 'CFBundleShortVersionString', + 'NSHumanReadableCopyright' + ].forEach(function(prop) { + if(!options.hasOwnProperty(prop)) { + throw new Error('Missing macPlist property \'' + prop + '\''); } + }); - // Handle the INfo.plist file - var info = plist.parse(fs.readFileSync(plistInput, 'utf8')); - info.CFBundleDisplayName = options.appName; - info.CFBundleName = options.appName; - info.CFBundleVersion = options.appVersion; - info.CFBundleShortVersionString = 'Version ' + options.appVersion; - if(options.copyright) { - info.NSHumanReadableCopyright = options.copyright; - } - if(options.mac_bundle_id) { - info.CFBundleIdentifier = options.mac_bundle_id; - } - if(options.mac_document_types) { - info.CFBundleDocumentTypes = options.mac_document_types.map(function(type) { - return { - CFBundleTypeName: type.name, - CFBundleTypeExtensions: type.extensions, - CFBundleTypeRole: type.role, - LSIsAppleDefaultForType: type.isDefault - }; + // Read the input file + return readFile(plistInput, 'utf8') + // Parse it + .then(plist.parse) + // Then overwrite the properties with custom values + .then(function(info) { + // Keep backwards compatibility and handle aliases + Object.keys(options).forEach(function(key) { + var value = options[key]; + switch(key) { + case 'mac_bundle_id': + info.CFBundleIdentifier = value; + break; + case 'mac_document_types': + info.CFBundleDocumentTypes = value.map(function(type) { + return { + CFBundleTypeName: type.name, + CFBundleTypeExtensions: type.extensions, + CFBundleTypeRole: type.role, + LSIsAppleDefaultForType: type.isDefault + }; + }); + break; + default: + info[key] = value; + } }); - } else { - info.CFBundleDocumentTypes = []; - } - info.UTExportedTypeDeclarations = []; - fs.writeFileSync(plistOutput, plist.build(info)); - resolve(); - }); + // Remove some unwanted properties + if(!options.hasOwnProperty('mac_document_types')) { + info.CFBundleDocumentTypes = []; + } + info.UTExportedTypeDeclarations = []; + + // Write output file + return writeFile(plistOutput, plist.build(info)); + }); } }; diff --git a/test/expected/Info.plist b/test/expected/Info.plist index 9fa20c25d..d9dc05178 100644 --- a/test/expected/Info.plist +++ b/test/expected/Info.plist @@ -5,7 +5,7 @@ CFBundleDevelopmentRegion en CFBundleDisplayName - TestApp + My cool TestApp CFBundleDocumentTypes CFBundleExecutable @@ -38,5 +38,10 @@ NSHumanReadableCopyright (c) by me + LSEnvironment + + PATH + /usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin + diff --git a/test/utils.js b/test/utils.js index b17e93769..5451ff23f 100644 --- a/test/utils.js +++ b/test/utils.js @@ -26,11 +26,19 @@ test('getPackageInfo valid', function (t) { test('editPlist', function (t) { t.plan(1); temp.open('plstest', function(err, info) { - utils.editPlist('./test/fixtures/Info.plist', info.path, { - appName: 'TestApp', - appVersion: '1.3.3.7', - copyright: '(c) by me' - }).then(function () { + utils.editPlist('./test/fixtures/Info.plist', info.path, utils.getPlistOptions( + { + name: 'TestApp', + version: '1.3.3.7', + copyright: '(c) by me' + }, + { + CFBundleDisplayName: "My cool TestApp", + LSEnvironment: { + PATH: '/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin' + } + } + )).then(function () { var actual = fs.readFileSync(info.path).toString().replace(/\r|\n/gm, ''); var expected = fs.readFileSync('./test/expected/Info.plist').toString().replace(/\r|\n/gm, ''); t.equal(actual, expected, 'generate and write a valid plist file');