diff --git a/app/package.json b/app/package.json index ce69686..7da9895 100644 --- a/app/package.json +++ b/app/package.json @@ -1,6 +1,7 @@ { "name": "electron-boilerplate", "productName": "Electron Boilerplate", + "identifier": "com.example.electron-boilerplate", "description": "Starter for your Electron application. Out of the box ready for serious stuff.", "version": "0.1.0", "author": "Mr Gumby ", diff --git a/gulpfile.js b/gulpfile.js index 42bf7a1..bc266bc 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,3 +1,4 @@ 'use strict'; require('./tasks/build'); +require('./tasks/release'); diff --git a/resources/icon.png b/resources/icon.png new file mode 100644 index 0000000..0533343 Binary files /dev/null and b/resources/icon.png differ diff --git a/resources/osx/Info.plist b/resources/osx/Info.plist new file mode 100644 index 0000000..a65de65 --- /dev/null +++ b/resources/osx/Info.plist @@ -0,0 +1,30 @@ + + + + + CFBundleDisplayName + {{productName}} + CFBundleExecutable + Electron + CFBundleIconFile + icon.icns + CFBundleIdentifier + {{identifier}} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + {{productName}} + CFBundlePackageType + APPL + CFBundleVersion + {{version}} + LSMinimumSystemVersion + 10.8.0 + NSMainNibFile + MainMenu + NSPrincipalClass + AtomApplication + NSSupportsAutomaticGraphicsSwitching + + + diff --git a/resources/osx/appdmg.json b/resources/osx/appdmg.json new file mode 100644 index 0000000..c0aff23 --- /dev/null +++ b/resources/osx/appdmg.json @@ -0,0 +1,10 @@ +{ + "title": "{{productName}}", + "icon": "{{dmgIcon}}", + "background": "{{dmgBackground}}", + "icon-size": 128, + "contents": [ + { "x": 410, "y": 220, "type": "link", "path": "/Applications" }, + { "x": 130, "y": 220, "type": "file", "path": "{{appPath}}" } + ] +} diff --git a/resources/osx/dmg-background.png b/resources/osx/dmg-background.png new file mode 100644 index 0000000..70476c2 Binary files /dev/null and b/resources/osx/dmg-background.png differ diff --git a/resources/osx/dmg-background@2x.png b/resources/osx/dmg-background@2x.png new file mode 100644 index 0000000..0c75142 Binary files /dev/null and b/resources/osx/dmg-background@2x.png differ diff --git a/resources/osx/dmg-icon.icns b/resources/osx/dmg-icon.icns new file mode 100644 index 0000000..f08f3b9 Binary files /dev/null and b/resources/osx/dmg-icon.icns differ diff --git a/resources/osx/helper_app/Info.plist b/resources/osx/helper_app/Info.plist new file mode 100644 index 0000000..ccbf6ba --- /dev/null +++ b/resources/osx/helper_app/Info.plist @@ -0,0 +1,18 @@ + + + + + CFBundleIdentifier + {{identifier}}.helper + CFBundleName + {{productName}} Helper + CFBundlePackageType + APPL + DTSDKName + macosx + LSUIElement + + NSSupportsAutomaticGraphicsSwitching + + + diff --git a/resources/osx/icon.icns b/resources/osx/icon.icns new file mode 100644 index 0000000..87348e8 Binary files /dev/null and b/resources/osx/icon.icns differ diff --git a/tasks/release.js b/tasks/release.js new file mode 100644 index 0000000..bcbeef2 --- /dev/null +++ b/tasks/release.js @@ -0,0 +1,14 @@ +'use strict'; + +var gulp = require('gulp'); +var utils = require('./utils'); + +var releaseForOs = { + osx: require('./release_osx'), + //linux: require('./release_linux'), + //windows: require('./release_windows'), +}; + +gulp.task('release', ['build'], function () { + return releaseForOs[utils.os()](); +}); diff --git a/tasks/release_osx.js b/tasks/release_osx.js new file mode 100644 index 0000000..d728a9e --- /dev/null +++ b/tasks/release_osx.js @@ -0,0 +1,105 @@ +'use strict'; + +var Q = require('q'); +var gulpUtil = require('gulp-util'); +var childProcess = require('child_process'); +var jetpack = require('fs-jetpack'); +var utils = require('./utils'); + +var projectDir; +var releasesDir; +var tmpDir; +var finalAppDir; +var manifest; + +var init = function () { + projectDir = jetpack; + tmpDir = projectDir.dir('./tmp', { empty: true }); + releasesDir = projectDir.dir('./releases'); + manifest = projectDir.read('app/package.json', 'json'); + finalAppDir = tmpDir.cwd(manifest.productName + '.app'); + + return Q(); +}; + +var copyRuntime = function () { + return projectDir.copyAsync('node_modules/electron-prebuilt/dist/Electron.app', finalAppDir.path()); +}; + +var copyBuiltApp = function () { + return projectDir.copyAsync('build', finalAppDir.path('Contents/Resources/app')); +}; + +var finalize = function () { + // Prepare main Info.plist + var info = projectDir.read('resources/osx/Info.plist'); + info = utils.replace(info, { + productName: manifest.productName, + identifier: manifest.identifier, + version: manifest.version + }); + finalAppDir.write('Contents/Info.plist', info); + + // Prepare Info.plist of Helper app + info = projectDir.read('resources/osx/helper_app/Info.plist'); + info = utils.replace(info, { + productName: manifest.productName, + identifier: manifest.identifier + }); + finalAppDir.write('Contents/Frameworks/Electron Helper.app/Contents/Info.plist', info); + + // Copy icon + projectDir.copy('resources/osx/icon.icns', finalAppDir.path('Contents/Resources/icon.icns')); + + return Q(); +}; + +var packToDmgFile = function () { + var deferred = Q.defer(); + + var appdmg = require('appdmg'); + var dmgName = manifest.name + '_' + manifest.version + '.dmg'; + + // Prepare appdmg config + var dmgManifest = projectDir.read('resources/osx/appdmg.json'); + dmgManifest = utils.replace(dmgManifest, { + productName: manifest.productName, + appPath: finalAppDir.path(), + dmgIcon: projectDir.path("resources/osx/dmg-icon.icns"), + dmgBackground: projectDir.path("resources/osx/dmg-background.png") + }); + tmpDir.write('appdmg.json', dmgManifest); + + // Delete DMG file with this name if already exists + releasesDir.remove(dmgName); + + gulpUtil.log('Packaging to DMG file...'); + + var readyDmgPath = releasesDir.path(dmgName); + appdmg({ + source: tmpDir.path('appdmg.json'), + target: readyDmgPath + }) + .on('error', function (err) { + console.error(err); + }) + .on('finish', function () { + gulpUtil.log('DMG file ready!', readyDmgPath); + deferred.resolve(); + }); + + return deferred.promise; +}; + +var cleanClutter = function () { + return tmpDir.removeAsync('.'); +}; + +module.exports = function () { + return init() + .then(copyRuntime) + .then(copyBuiltApp) + .then(finalize) + .then(packToDmgFile) + .then(cleanClutter); +};