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');