diff --git a/docs/api.md b/docs/api.md index 0591a577..05f32dd4 100644 --- a/docs/api.md +++ b/docs/api.md @@ -373,15 +373,15 @@ option. Maps to the `CFBundleURLName` metadata property. *Object* Object (also known as a "hash") of application metadata to embed into the executable: -- `CompanyName` -- `FileDescription` -- `OriginalFilename` -- `ProductName` -- `InternalName` +- `CompanyName` (defaults to `author` name from the nearest `package.json`) +- `FileDescription` (defaults to `description` from the nearest `package.json`) +- `OriginalFilename` (defaults to renamed `.exe` file) +- `ProductName` (defaults to either `productName` or `name` from the nearest `package.json`) +- `InternalName` (defaults to either `productName` or `name` from the nearest `package.json`) - `requested-execution-level` - `application-manifest` -For more information, see the [node-rcedit module](https://github.com/electron/node-rcedit). +For more information, see the [`node-rcedit` module](https://github.com/electron/node-rcedit). ## callback diff --git a/index.js b/index.js index 44d043c5..018022bf 100644 --- a/index.js +++ b/index.js @@ -150,7 +150,7 @@ module.exports = pify(function packager (opts, cb) { common.camelCase(opts, true) - getMetadataFromPackageJSON(opts, path.resolve(process.cwd(), opts.dir) || process.cwd(), function (err) { + getMetadataFromPackageJSON(platforms, opts, path.resolve(process.cwd(), opts.dir) || process.cwd(), function (err) { if (err) return cb(err) if (/ Helper$/.test(opts.name)) { diff --git a/infer.js b/infer.js index d081ab19..83f75205 100644 --- a/infer.js +++ b/infer.js @@ -2,6 +2,7 @@ const debug = require('debug')('electron-packager') const getPackageInfo = require('get-package-info') +const parseAuthor = require('parse-author') const path = require('path') const resolve = require('resolve') @@ -61,7 +62,7 @@ function getVersion (opts, electronProp, cb) { } } -module.exports = function getMetadataFromPackageJSON (opts, dir, cb) { +module.exports = function getMetadataFromPackageJSON (platforms, opts, dir, cb) { let props = [] if (!opts.name) props.push(['productName', 'name']) if (!opts.appVersion) props.push('version') @@ -76,6 +77,16 @@ module.exports = function getMetadataFromPackageJSON (opts, dir, cb) { ]) } + if (platforms.indexOf('win32') !== -1) { + if (!(opts.win32metadata && opts.win32metadata.FileDescription)) { + props.push('description') + } + + if (!(opts.win32metadata && opts.win32metadata.CompanyName)) { + props.push('author') + } + } + // Name and version provided, no need to infer if (props.length === 0) return cb(null) @@ -110,6 +121,20 @@ module.exports = function getMetadataFromPackageJSON (opts, dir, cb) { opts.appVersion = result.values.version } + if ((result.values.description || result.values.author) && !opts.win32metadata) { + opts.win32metadata = {} + } + + if (result.values.description) { + debug(`Inferring win32metadata.FileDescription from description in ${result.source.description.src}`) + opts.win32metadata.FileDescription = result.values.description + } + + if (result.values.author) { + debug(`Inferring win32metadata.CompanyName from description in ${result.source.author.src}`) + opts.win32metadata.CompanyName = parseAuthor(result.values.author).name + } + if (result.values['dependencies.electron']) { return getVersion(opts, result.source['dependencies.electron'], cb) } else { diff --git a/package.json b/package.json index 894b9d7d..28c4e208 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "fs-extra": "^3.0.0", "get-package-info": "^1.0.0", "minimist": "^1.1.1", + "parse-author": "^2.0.0", "pify": "^3.0.0", "plist": "^2.0.0", "rcedit": "^0.9.0", diff --git a/test/fixtures/infer-win32metadata/package.json b/test/fixtures/infer-win32metadata/package.json new file mode 100644 index 00000000..088779de --- /dev/null +++ b/test/fixtures/infer-win32metadata/package.json @@ -0,0 +1,9 @@ +{ + "main": "main.js", + "productName": "MainJS", + "author": "Foo Bar ", + "description": "Some description", + "devDependencies": { + "electron-prebuilt-compile": "1.4.15" + } +} diff --git a/test/infer.js b/test/infer.js index f58ceeab..2c133b9c 100644 --- a/test/infer.js +++ b/test/infer.js @@ -19,7 +19,7 @@ function createInferElectronVersionTest (fixture, packageName) { delete opts.electronVersion opts.dir = path.join(__dirname, 'fixtures', fixture) - pify(getMetadataFromPackageJSON)(opts, opts.dir) + pify(getMetadataFromPackageJSON)([], opts, opts.dir) .then((pkg) => { const packageJSON = require(path.join(opts.dir, 'package.json')) t.equal(opts.electronVersion, packageJSON.devDependencies[packageName], `The version should be inferred from installed ${packageName} version`) @@ -71,7 +71,7 @@ function createInferMissingVersionTest (opts) { delete opts.electronVersion opts.dir = dir - return pify(getMetadataFromPackageJSON)(opts, dir) + return pify(getMetadataFromPackageJSON)([], opts, dir) }).then(() => { const packageJSON = require(path.join(opts.dir, 'package.json')) t.equal(opts.electronVersion, packageJSON.devDependencies['electron'], 'The version should be inferred from installed electron module version') @@ -80,6 +80,19 @@ function createInferMissingVersionTest (opts) { } } +function testInferWin32metadata (t, opts, expected, assertionMessage) { + t.timeoutAfter(config.timeout) + copyFixtureToTempDir('infer-win32metadata') + .then((dir) => { + opts.dir = dir + + return pify(getMetadataFromPackageJSON)(['win32'], opts, dir) + }).then(() => { + t.deepEqual(opts.win32metadata, expected, assertionMessage) + return t.end() + }).catch(t.end) +} + function createInferMissingFieldsTest (opts) { return createInferFailureTest(opts, 'infer-missing-fields') } @@ -100,6 +113,27 @@ util.testSinglePlatform('infer using `electron-prebuilt` package', createInferEl util.testSinglePlatform('infer using `electron-prebuilt-compile` package', createInferElectronVersionTest('infer-electron-prebuilt-compile', 'electron-prebuilt-compile')) util.testSinglePlatform('infer using `electron` package only', createInferMissingVersionTest) util.testSinglePlatform('infer where `electron` version is preferred over `electron-prebuilt`', createInferElectronVersionTest('basic-renamed-to-electron', 'electron')) +util.testSinglePlatform('infer win32metadata', (opts) => { + return (t) => { + const expected = { + CompanyName: 'Foo Bar', + FileDescription: 'Some description' + } + + testInferWin32metadata(t, opts, expected, 'win32metadata matches package.json values') + } +}) +util.testSinglePlatform('do not infer win32metadata if it already exists', (opts) => { + return (t) => { + opts.win32metadata = { + CompanyName: 'Existing', + FileDescription: 'Existing description' + } + const expected = Object.assign({}, opts.win32metadata) + + testInferWin32metadata(t, opts, expected, 'win32metadata did not update with package.json values') + } +}) util.testSinglePlatform('infer missing fields test', createInferMissingFieldsTest) util.testSinglePlatform('infer with bad fields test', createInferWithBadFieldsTest) util.testSinglePlatform('infer with malformed JSON test', createInferWithMalformedJSONTest) diff --git a/test/win32.js b/test/win32.js index 9f8697d4..3341ba15 100644 --- a/test/win32.js +++ b/test/win32.js @@ -163,6 +163,18 @@ test('error message unchanged when error not about wine', (t) => { t.end() }) +test('win32metadata defaults', (t) => { + const opts = { + name: 'Win32 App' + } + const rcOpts = win32.generateRceditOptionsSansIcon(opts, 'Win32 App.exe') + + t.equal(rcOpts['version-string'].InternalName, opts.name) + t.equal(rcOpts['version-string'].OriginalFilename, 'Win32 App.exe') + t.equal(rcOpts['version-string'].ProductName, opts.name) + t.end() +}) + util.packagerTest('win32 executable name is based on sanitized app name', (t) => { const opts = Object.assign({}, baseOpts, {name: '@username/package-name'}) diff --git a/usage.txt b/usage.txt index 7f1107d9..c477fcf8 100644 --- a/usage.txt +++ b/usage.txt @@ -88,10 +88,10 @@ win32metadata a list of sub-properties used to set the application metadata e.g. --win32metadata.CompanyName="Company Inc." or --win32metadata.ProductName="Product" Properties supported: - - CompanyName - - FileDescription - - OriginalFilename - - ProductName - - InternalName + - CompanyName (default: author name from nearest package.json) + - FileDescription (default: description from nearest package.json) + - OriginalFilename (default: renamed exe) + - ProductName (default: appname) + - InternalName (default: appname) - requested-execution-level (user, asInvoker, or requireAdministrator) - application-manifest diff --git a/win32.js b/win32.js index 64310728..33da648e 100644 --- a/win32.js +++ b/win32.js @@ -5,8 +5,12 @@ const debug = require('debug')('electron-packager') const path = require('path') const series = require('run-series') -function generateRceditOptionsSansIcon (opts) { - const win32metadata = Object.assign({}, opts['version-string'], opts.win32metadata) +function generateRceditOptionsSansIcon (opts, newExeName) { + const win32metadata = Object.assign({ + InternalName: opts.name, + OriginalFilename: newExeName, + ProductName: opts.name + }, opts['version-string'], opts.win32metadata) let rcOpts = {'version-string': win32metadata} @@ -56,7 +60,7 @@ module.exports = { } ] - const rcOpts = generateRceditOptionsSansIcon(opts) + const rcOpts = generateRceditOptionsSansIcon(opts, newExeName) if (opts.icon || opts.win32metadata || opts['version-string'] || opts.appCopyright || opts.appVersion || opts.buildVersion) { operations.push(function (cb) {