From 95fc46d38d1610efcfc6f4518a4e3d15864023b8 Mon Sep 17 00:00:00 2001 From: Goh Jia Hao Date: Thu, 24 May 2018 00:02:44 -0700 Subject: [PATCH] Integrate prettier --- .editorconfig | 2 +- .eslintrc.yml | 8 +- .prettierrc.yaml | 3 + app/src/components/login/loginWindow.js | 4 +- app/src/components/mainWindow/mainWindow.js | 118 +++++++++----- app/src/components/menu/menu.js | 7 +- app/src/components/trayIcon/trayIcon.js | 4 +- app/src/helpers/inferFlash.js | 13 +- app/src/main.js | 22 ++- gulp/build/build-app.js | 9 +- gulp/build/build-cli.js | 4 +- gulp/build/build-static.js | 11 +- gulp/helpers/gulp-helpers.js | 3 +- gulp/release.js | 2 +- package.json | 6 +- src/build/buildApp.js | 53 +++--- src/build/buildMain.js | 143 ++++++++-------- src/build/iconBuild.js | 4 +- src/cli.js | 171 ++++++++++++++++---- src/helpers/convertToIcns.js | 33 ++-- src/helpers/helpers.js | 15 +- src/helpers/iconShellHelpers.js | 54 +++++-- src/infer/inferIcon.js | 66 ++++---- src/infer/inferOs.js | 7 +- src/infer/inferTitle.js | 8 +- src/infer/inferUserAgent.js | 52 +++--- src/infer/inferUserAgent.test.js | 8 +- src/options/asyncConfig.js | 12 +- src/options/asyncConfig.test.js | 9 +- src/options/fields/icon.js | 11 +- src/options/fields/icon.test.js | 9 +- src/options/fields/index.js | 33 ++-- src/options/fields/index.test.js | 1 - src/options/fields/name.js | 13 +- src/options/fields/name.test.js | 34 ++-- src/options/fields/userAgent.js | 2 +- src/options/fields/userAgent.test.js | 6 +- src/options/normalizeUrl.test.js | 8 +- src/options/optionsMain.js | 7 +- src/utils/sanitizeFilename.js | 2 +- src/utils/sanitizeFilename.test.js | 2 +- 41 files changed, 632 insertions(+), 347 deletions(-) create mode 100644 .prettierrc.yaml diff --git a/.editorconfig b/.editorconfig index 385ede0..e9f3a67 100644 --- a/.editorconfig +++ b/.editorconfig @@ -13,7 +13,7 @@ insert_final_newline = true [*.{js,py}] charset = utf-8 indent_style = space -indent_size = 4 +indent_size = 2 # 2 space indentation [*.{html,css,less,scss,yml,json}] diff --git a/.eslintrc.yml b/.eslintrc.yml index 15f66cb..d81db00 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -1,11 +1,15 @@ -extends: airbnb-base -env: +extends: + - airbnb-base + - prettier +env: # TODO: find out how to turn this on only for src/**/*.test.js files jest: true plugins: - import + - prettier rules: # TODO: Remove this when we have shifted away from the async package no-shadow: 'warn' # Gulpfiles and tests use dev dependencies import/no-extraneous-dependencies: ['error', { devDependencies: ['gulpfile.babel.js', 'gulp/**/**.js', 'test/**/**.js']}] + prettier/prettier: "error" diff --git a/.prettierrc.yaml b/.prettierrc.yaml new file mode 100644 index 0000000..6e5d5e0 --- /dev/null +++ b/.prettierrc.yaml @@ -0,0 +1,3 @@ +arrowParens: always +singleQuote: true +trailingComma: all diff --git a/app/src/components/login/loginWindow.js b/app/src/components/login/loginWindow.js index 12f7e1f..092a434 100644 --- a/app/src/components/login/loginWindow.js +++ b/app/src/components/login/loginWindow.js @@ -8,7 +8,9 @@ function createLoginWindow(loginCallback) { frame: false, resizable: false, }); - loginWindow.loadURL(`file://${path.join(__dirname, '/static/login/login.html')}`); + loginWindow.loadURL( + `file://${path.join(__dirname, '/static/login/login.html')}`, + ); ipcMain.once('login-message', (event, usernameAndPassword) => { loginCallback(usernameAndPassword[0], usernameAndPassword[1]); diff --git a/app/src/components/mainWindow/mainWindow.js b/app/src/components/mainWindow/mainWindow.js index e38085c..d22a325 100644 --- a/app/src/components/mainWindow/mainWindow.js +++ b/app/src/components/mainWindow/mainWindow.js @@ -7,7 +7,12 @@ import createMenu from './../menu/menu'; import initContextMenu from './../contextMenu/contextMenu'; const { - isOSX, linkIsInternal, getCssToInject, shouldInjectCss, getAppIcon, nativeTabsSupported, + isOSX, + linkIsInternal, + getCssToInject, + shouldInjectCss, + getAppIcon, + nativeTabsSupported, } = helpers; const ZOOM_INTERVAL = 0.1; @@ -37,7 +42,10 @@ function maybeInjectCss(browserWindow) { browserWindow.webContents.on('did-finish-load', () => { // remove the injection of css the moment the page is loaded - browserWindow.webContents.removeListener('did-get-response-details', injectCss); + browserWindow.webContents.removeListener( + 'did-get-response-details', + injectCss, + ); }); // on every page navigation inject the css @@ -48,7 +56,6 @@ function maybeInjectCss(browserWindow) { }); } - /** * * @param {{}} inpOptions AppArgs from nativefier.json @@ -78,24 +85,29 @@ function createMainWindow(inpOptions, onAppQuit, setDockBadge) { }, }; - const mainWindow = new BrowserWindow(Object.assign({ - frame: !options.hideWindowFrame, - width: mainWindowState.width, - height: mainWindowState.height, - minWidth: options.minWidth, - minHeight: options.minHeight, - maxWidth: options.maxWidth, - maxHeight: options.maxHeight, - x: options.x, - y: options.y, - autoHideMenuBar: !options.showMenuBar, - // after webpack path here should reference `resources/app/` - icon: getAppIcon(), - // set to undefined and not false because explicitly setting to false will disable full screen - fullscreen: options.fullScreen || undefined, - // Whether the window should always stay on top of other windows. Default is false. - alwaysOnTop: options.alwaysOnTop, - }, DEFAULT_WINDOW_OPTIONS)); + const mainWindow = new BrowserWindow( + Object.assign( + { + frame: !options.hideWindowFrame, + width: mainWindowState.width, + height: mainWindowState.height, + minWidth: options.minWidth, + minHeight: options.minHeight, + maxWidth: options.maxWidth, + maxHeight: options.maxHeight, + x: options.x, + y: options.y, + autoHideMenuBar: !options.showMenuBar, + // after webpack path here should reference `resources/app/` + icon: getAppIcon(), + // set to undefined and not false because explicitly setting to false will disable full screen + fullscreen: options.fullScreen || undefined, + // Whether the window should always stay on top of other windows. Default is false. + alwaysOnTop: options.alwaysOnTop, + }, + DEFAULT_WINDOW_OPTIONS, + ), + ); mainWindowState.manage(mainWindow); @@ -103,12 +115,17 @@ function createMainWindow(inpOptions, onAppQuit, setDockBadge) { if (options.maximize) { mainWindow.maximize(); options.maximize = undefined; - fs.writeFileSync(path.join(__dirname, '..', 'nativefier.json'), JSON.stringify(options)); + fs.writeFileSync( + path.join(__dirname, '..', 'nativefier.json'), + JSON.stringify(options), + ); } const withFocusedWindow = (block) => { const focusedWindow = BrowserWindow.getFocusedWindow(); - if (focusedWindow) { block(focusedWindow); } + if (focusedWindow) { + block(focusedWindow); + } }; const adjustWindowZoom = (window, adjustment) => { @@ -118,11 +135,15 @@ function createMainWindow(inpOptions, onAppQuit, setDockBadge) { }; const onZoomIn = () => { - withFocusedWindow(focusedWindow => adjustWindowZoom(focusedWindow, ZOOM_INTERVAL)); + withFocusedWindow((focusedWindow) => + adjustWindowZoom(focusedWindow, ZOOM_INTERVAL), + ); }; const onZoomOut = () => { - withFocusedWindow(focusedWindow => adjustWindowZoom(focusedWindow, -ZOOM_INTERVAL)); + withFocusedWindow((focusedWindow) => + adjustWindowZoom(focusedWindow, -ZOOM_INTERVAL), + ); }; const onZoomReset = () => { @@ -132,23 +153,28 @@ function createMainWindow(inpOptions, onAppQuit, setDockBadge) { }; const clearAppData = () => { - dialog.showMessageBox(mainWindow, { - type: 'warning', - buttons: ['Yes', 'Cancel'], - defaultId: 1, - title: 'Clear cache confirmation', - message: 'This will clear all data (cookies, local storage etc) from this app. Are you sure you wish to proceed?', - }, (response) => { - if (response !== 0) { - return; - } - const { session } = mainWindow.webContents; - session.clearStorageData(() => { - session.clearCache(() => { - mainWindow.loadURL(options.targetUrl); + dialog.showMessageBox( + mainWindow, + { + type: 'warning', + buttons: ['Yes', 'Cancel'], + defaultId: 1, + title: 'Clear cache confirmation', + message: + 'This will clear all data (cookies, local storage etc) from this app. Are you sure you wish to proceed?', + }, + (response) => { + if (response !== 0) { + return; + } + const { session } = mainWindow.webContents; + session.clearStorageData(() => { + session.clearCache(() => { + mainWindow.loadURL(options.targetUrl); + }); }); - }); - }); + }, + ); }; const onGoBack = () => { @@ -236,7 +262,10 @@ function createMainWindow(inpOptions, onAppQuit, setDockBadge) { createMenu(menuOptions); if (!options.disableContextMenu) { - initContextMenu(createNewWindow, nativeTabsSupported() ? createNewTab : undefined); + initContextMenu( + createNewWindow, + nativeTabsSupported() ? createNewTab : undefined, + ); } if (options.userAgent) { @@ -280,7 +309,10 @@ function createMainWindow(inpOptions, onAppQuit, setDockBadge) { mainWindow.moveTabToNewWindow(); } mainWindow.setFullScreen(false); - mainWindow.once('leave-full-screen', maybeHideWindow.bind(this, mainWindow, event, options.fastQuit)); + mainWindow.once( + 'leave-full-screen', + maybeHideWindow.bind(this, mainWindow, event, options.fastQuit), + ); } maybeHideWindow(mainWindow, event, options.fastQuit, options.tray); }); diff --git a/app/src/components/menu/menu.js b/app/src/components/menu/menu.js index 295be0b..b0c7759 100644 --- a/app/src/components/menu/menu.js +++ b/app/src/components/menu/menu.js @@ -29,9 +29,10 @@ function createMenu({ if (Menu.getApplicationMenu()) { return; } - const zoomResetLabel = (zoomBuildTimeValue === 1.0) ? - 'Reset Zoom' : - `Reset Zoom (to ${zoomBuildTimeValue * 100}%, set at build time)`; + const zoomResetLabel = + zoomBuildTimeValue === 1.0 + ? 'Reset Zoom' + : `Reset Zoom (to ${zoomBuildTimeValue * 100}%, set at build time)`; const template = [ { diff --git a/app/src/components/trayIcon/trayIcon.js b/app/src/components/trayIcon/trayIcon.js index 82f6e91..c6433f0 100644 --- a/app/src/components/trayIcon/trayIcon.js +++ b/app/src/components/trayIcon/trayIcon.js @@ -1,8 +1,6 @@ import helpers from './../../helpers/helpers'; -const { - app, Tray, Menu, ipcMain, nativeImage, -} = require('electron'); +const { app, Tray, Menu, ipcMain, nativeImage } = require('electron'); const { getAppIcon } = helpers; diff --git a/app/src/helpers/inferFlash.js b/app/src/helpers/inferFlash.js index d5f5c0b..e674754 100644 --- a/app/src/helpers/inferFlash.js +++ b/app/src/helpers/inferFlash.js @@ -47,7 +47,7 @@ function findSync(pattern, basePath, findDir) { matches.push(childPath); } }); - }(basePath)); + })(basePath); return matches; } @@ -56,11 +56,18 @@ function linuxMatch() { } function windowsMatch() { - return findSync(/pepflashplayer\.dll/, 'C:\\Program Files (x86)\\Google\\Chrome')[0]; + return findSync( + /pepflashplayer\.dll/, + 'C:\\Program Files (x86)\\Google\\Chrome', + )[0]; } function darwinMatch() { - return findSync(/PepperFlashPlayer.plugin/, '/Applications/Google Chrome.app/', true)[0]; + return findSync( + /PepperFlashPlayer.plugin/, + '/Applications/Google Chrome.app/', + true, + )[0]; } function inferFlash() { diff --git a/app/src/main.js b/app/src/main.js index 6aa7fdd..abc6595 100644 --- a/app/src/main.js +++ b/app/src/main.js @@ -55,11 +55,17 @@ if (appArgs.diskCacheSize) { } if (appArgs.basicAuthUsername) { - app.commandLine.appendSwitch('basic-auth-username', appArgs.basicAuthUsername); + app.commandLine.appendSwitch( + 'basic-auth-username', + appArgs.basicAuthUsername, + ); } if (appArgs.basicAuthPassword) { - app.commandLine.appendSwitch('basic-auth-password', appArgs.basicAuthPassword); + app.commandLine.appendSwitch( + 'basic-auth-password', + appArgs.basicAuthPassword, + ); } // do nothing for setDockBadge if not OSX @@ -126,7 +132,10 @@ app.on('login', (event, webContents, request, authInfo, callback) => { // for http authentication event.preventDefault(); - if (appArgs.basicAuthUsername !== null && appArgs.basicAuthPassword !== null) { + if ( + appArgs.basicAuthUsername !== null && + appArgs.basicAuthPassword !== null + ) { callback(appArgs.basicAuthUsername, appArgs.basicAuthPassword); } else { createLoginWindow(callback); @@ -137,9 +146,12 @@ if (appArgs.singleInstance) { const shouldQuit = app.makeSingleInstance(() => { // Someone tried to run a second instance, we should focus our window. if (mainWindow) { - if (!mainWindow.isVisible()) { // tray + if (!mainWindow.isVisible()) { + // tray mainWindow.show(); - } if (mainWindow.isMinimized()) { // minimized + } + if (mainWindow.isMinimized()) { + // minimized mainWindow.restore(); } mainWindow.focus(); diff --git a/gulp/build/build-app.js b/gulp/build/build-app.js index 7df56d2..b067c5e 100644 --- a/gulp/build/build-app.js +++ b/gulp/build/build-app.js @@ -4,6 +4,9 @@ import PATHS from './../helpers/src-paths'; const webpackConfig = require('./../../webpack.config.js'); -gulp.task('build-app', ['build-static'], () => gulp.src(PATHS.APP_MAIN_JS) - .pipe(webpack(webpackConfig)) - .pipe(gulp.dest(PATHS.APP_DEST))); +gulp.task('build-app', ['build-static'], () => + gulp + .src(PATHS.APP_MAIN_JS) + .pipe(webpack(webpackConfig)) + .pipe(gulp.dest(PATHS.APP_DEST)), +); diff --git a/gulp/build/build-cli.js b/gulp/build/build-cli.js index a3b54c5..7ca52e0 100644 --- a/gulp/build/build-cli.js +++ b/gulp/build/build-cli.js @@ -4,4 +4,6 @@ import helpers from './../helpers/gulp-helpers'; const { buildES6 } = helpers; -gulp.task('build-cli', done => buildES6(PATHS.CLI_SRC_JS, PATHS.CLI_DEST, done)); +gulp.task('build-cli', (done) => + buildES6(PATHS.CLI_SRC_JS, PATHS.CLI_DEST, done), +); diff --git a/gulp/build/build-static.js b/gulp/build/build-static.js index 1ecd88e..3a7b6e9 100644 --- a/gulp/build/build-static.js +++ b/gulp/build/build-static.js @@ -4,9 +4,14 @@ import helpers from './../helpers/gulp-helpers'; const { buildES6 } = helpers; -gulp.task('build-static-not-js', () => gulp.src([PATHS.APP_STATIC_ALL, '!**/*.js']) - .pipe(gulp.dest(PATHS.APP_STATIC_DEST))); +gulp.task('build-static-not-js', () => + gulp + .src([PATHS.APP_STATIC_ALL, '!**/*.js']) + .pipe(gulp.dest(PATHS.APP_STATIC_DEST)), +); -gulp.task('build-static-js', done => buildES6(PATHS.APP_STATIC_JS, PATHS.APP_STATIC_DEST, done)); +gulp.task('build-static-js', (done) => + buildES6(PATHS.APP_STATIC_JS, PATHS.APP_STATIC_DEST, done), +); gulp.task('build-static', ['build-static-js', 'build-static-not-js']); diff --git a/gulp/helpers/gulp-helpers.js b/gulp/helpers/gulp-helpers.js index 82149d8..fa3109d 100644 --- a/gulp/helpers/gulp-helpers.js +++ b/gulp/helpers/gulp-helpers.js @@ -14,7 +14,8 @@ function shellExec(cmd, silent, callback) { } function buildES6(src, dest, callback) { - return gulp.src(src) + return gulp + .src(src) .pipe(sourcemaps.init()) .pipe(babel()) .on('error', callback) diff --git a/gulp/release.js b/gulp/release.js index 4e7dd98..d22f344 100644 --- a/gulp/release.js +++ b/gulp/release.js @@ -8,4 +8,4 @@ gulp.task('publish', (done) => { shellExec('npm publish', false, done); }); -gulp.task('release', callback => runSequence('build', 'publish', callback)); +gulp.task('release', (callback) => runSequence('build', 'publish', callback)); diff --git a/package.json b/package.json index 5433eba..8a12c6b 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,8 @@ "watch": "while true ; do gulp watch ; done", "package-placeholder": "npm run build && node lib/cli.js http://www.bennish.net/web-notifications.html ~/Desktop --overwrite --name notification-test --icon ./test-resources/iconSampleGrey.png --inject ./test-resources/test-injection.js --inject ./test-resources/test-injection.css && open ~/Desktop/notification-test-darwin-x64/notification-test.app", "start-placeholder": "npm run build && electron app", - "changelog": "./scripts/changelog" + "changelog": "./scripts/changelog", + "format": "prettier --write '{gulp,src}/**/*.js' 'app/src/**/*.js'" }, "bin": { "nativefier": "lib/cli.js" @@ -68,11 +69,14 @@ "del": "^3.0.0", "eslint": "^4.17.0", "eslint-config-airbnb-base": "^12.1.0", + "eslint-config-prettier": "^2.9.0", "eslint-plugin-import": "^2.8.0", + "eslint-plugin-prettier": "^2.6.0", "gulp": "^3.9.1", "gulp-babel": "^7.0.1", "gulp-sourcemaps": "^2.6.4", "jest": "^22.1.4", + "prettier": "^1.12.1", "regenerator-runtime": "^0.11.1", "require-dir": "^1.0.0", "run-sequence": "^2.2.1", diff --git a/src/build/buildApp.js b/src/build/buildApp.js index a06bd9a..60f2430 100644 --- a/src/build/buildApp.js +++ b/src/build/buildApp.js @@ -64,30 +64,33 @@ function maybeCopyScripts(srcs, dest) { resolve(); }); } - const promises = srcs.map(src => new Promise((resolve, reject) => { - if (!fs.existsSync(src)) { - reject(new Error('Error copying injection files: file not found')); - return; - } + const promises = srcs.map( + (src) => + new Promise((resolve, reject) => { + if (!fs.existsSync(src)) { + reject(new Error('Error copying injection files: file not found')); + return; + } - let destFileName; - if (path.extname(src) === '.js') { - destFileName = 'inject.js'; - } else if (path.extname(src) === '.css') { - destFileName = 'inject.css'; - } else { - resolve(); - return; - } + let destFileName; + if (path.extname(src) === '.js') { + destFileName = 'inject.js'; + } else if (path.extname(src) === '.css') { + destFileName = 'inject.css'; + } else { + resolve(); + return; + } - copy(src, path.join(dest, 'inject', destFileName), (error) => { - if (error) { - reject(new Error(`Error Copying injection files: ${error}`)); - return; - } - resolve(); - }); - })); + copy(src, path.join(dest, 'inject', destFileName), (error) => { + if (error) { + reject(new Error(`Error Copying injection files: ${error}`)); + return; + } + resolve(); + }); + }), + ); return new Promise((resolve, reject) => { Promise.all(promises) @@ -133,7 +136,10 @@ function buildApp(src, dest, options, callback) { return; } - fs.writeFileSync(path.join(dest, '/nativefier.json'), JSON.stringify(appArgs)); + fs.writeFileSync( + path.join(dest, '/nativefier.json'), + JSON.stringify(appArgs), + ); maybeCopyScripts(options.inject, dest) .catch((err) => { @@ -146,5 +152,4 @@ function buildApp(src, dest, options, callback) { }); } - export default buildApp; diff --git a/src/build/buildMain.js b/src/build/buildMain.js index a7207b7..1833a8a 100644 --- a/src/build/buildMain.js +++ b/src/build/buildMain.js @@ -28,7 +28,10 @@ function getAppPath(appPathArray) { } if (appPathArray.length > 1) { - log.warn('Warning: This should not be happening, packaged app path contains more than one element:', appPathArray); + log.warn( + 'Warning: This should not be happening, packaged app path contains more than one element:', + appPathArray, + ); } return appPathArray[0]; @@ -43,7 +46,9 @@ function maybeNoIconOption(options) { const packageOptions = JSON.parse(JSON.stringify(options)); if (options.platform === 'win32' && !isWindows()) { if (!hasBinary.sync('wine')) { - log.warn('Wine is required to set the icon for a Windows app when packaging on non-windows platforms'); + log.warn( + 'Wine is required to set the icon for a Windows app when packaging on non-windows platforms', + ); packageOptions.icon = null; } } @@ -86,7 +91,9 @@ function removeInvalidOptions(options, param) { const packageOptions = JSON.parse(JSON.stringify(options)); if (options.platform === 'win32' && !isWindows()) { if (!hasBinary.sync('wine')) { - log.warn(`Wine is required to use "${param}" option for a Windows app when packaging on non-windows platforms`); + log.warn( + `Wine is required to use "${param}" option for a Windows app when packaging on non-windows platforms`, + ); packageOptions[param] = null; } } @@ -161,74 +168,80 @@ function buildMain(inpOptions, callback) { const progress = new DishonestProgress(5); - async.waterfall([ - (cb) => { - progress.tick('inferring'); - optionsFactory(options) - .then((result) => { - cb(null, result); - }).catch((error) => { - cb(error); + async.waterfall( + [ + (cb) => { + progress.tick('inferring'); + optionsFactory(options) + .then((result) => { + cb(null, result); + }) + .catch((error) => { + cb(error); + }); + }, + (opts, cb) => { + progress.tick('copying'); + buildApp(opts.dir, tmpPath, opts, (error) => { + if (error) { + cb(error); + return; + } + // Change the reference file for the Electron app to be the temporary path + const newOptions = Object.assign({}, opts, { + dir: tmpPath, + }); + cb(null, newOptions); }); - }, - (opts, cb) => { - progress.tick('copying'); - buildApp(opts.dir, tmpPath, opts, (error) => { - if (error) { - cb(error); + }, + (opts, cb) => { + progress.tick('icons'); + iconBuild(opts, (error, optionsWithIcon) => { + cb(null, optionsWithIcon); + }); + }, + (opts, cb) => { + progress.tick('packaging'); + // maybe skip passing icon parameter to electron packager + let packageOptions = maybeNoIconOption(opts); + // maybe skip passing other parameters to electron packager + packageOptions = maybeNoAppCopyrightOption(packageOptions); + packageOptions = maybeNoAppVersionOption(packageOptions); + packageOptions = maybeNoBuildVersionOption(packageOptions); + packageOptions = maybeNoVersionStringOption(packageOptions); + packageOptions = maybeNoWin32metadataOption(packageOptions); + + packagerConsole.override(); + + packager(packageOptions) + .then((appPathArray) => { + packagerConsole.restore(); // restore console.error + cb(null, opts, appPathArray); // options still contain the icon to waterfall + }) + .catch((error) => { + packagerConsole.restore(); // restore console.error + cb(error, opts); // options still contain the icon to waterfall + }); + }, + (opts, appPathArray, cb) => { + progress.tick('finalizing'); + // somehow appPathArray is a 1 element array + const appPath = getAppPath(appPathArray); + if (!appPath) { + cb(); return; } - // Change the reference file for the Electron app to be the temporary path - const newOptions = Object.assign({}, opts, { dir: tmpPath }); - cb(null, newOptions); - }); - }, - (opts, cb) => { - progress.tick('icons'); - iconBuild(opts, (error, optionsWithIcon) => { - cb(null, optionsWithIcon); - }); - }, - (opts, cb) => { - progress.tick('packaging'); - // maybe skip passing icon parameter to electron packager - let packageOptions = maybeNoIconOption(opts); - // maybe skip passing other parameters to electron packager - packageOptions = maybeNoAppCopyrightOption(packageOptions); - packageOptions = maybeNoAppVersionOption(packageOptions); - packageOptions = maybeNoBuildVersionOption(packageOptions); - packageOptions = maybeNoVersionStringOption(packageOptions); - packageOptions = maybeNoWin32metadataOption(packageOptions); - packagerConsole.override(); - - packager(packageOptions) - .then((appPathArray) => { - packagerConsole.restore(); // restore console.error - cb(null, opts, appPathArray); // options still contain the icon to waterfall - }) - .catch((error) => { - packagerConsole.restore(); // restore console.error - cb(error, opts); // options still contain the icon to waterfall + maybeCopyIcons(opts, appPath, (error) => { + cb(error, appPath); }); + }, + ], + (error, appPath) => { + packagerConsole.playback(); + callback(error, appPath); }, - (opts, appPathArray, cb) => { - progress.tick('finalizing'); - // somehow appPathArray is a 1 element array - const appPath = getAppPath(appPathArray); - if (!appPath) { - cb(); - return; - } - - maybeCopyIcons(opts, appPath, (error) => { - cb(error, appPath); - }); - }, - ], (error, appPath) => { - packagerConsole.playback(); - callback(error, appPath); - }); + ); } export default buildMain; diff --git a/src/build/iconBuild.js b/src/build/iconBuild.js index 797389c..ab574c2 100644 --- a/src/build/iconBuild.js +++ b/src/build/iconBuild.js @@ -84,7 +84,9 @@ function iconBuild(inpOptions, callback) { } if (!isOSX()) { - log.warn('Skipping icon conversion to .icns, conversion is only supported on OSX'); + log.warn( + 'Skipping icon conversion to .icns, conversion is only supported on OSX', + ); returnCallback(); return; } diff --git a/src/cli.js b/src/cli.js index f9ff700..f32bb7c 100755 --- a/src/cli.js +++ b/src/cli.js @@ -28,12 +28,13 @@ function getProcessEnvs(val) { function checkInternet() { dns.lookup('npmjs.com', (err) => { if (err && err.code === 'ENOTFOUND') { - log.warn('\nNo Internet Connection\nTo offline build, download electron from https://github.com/electron/electron/releases\nand place in ~/AppData/Local/electron/Cache/ on Windows,\n~/.cache/electron on Linux or ~/Library/Caches/electron/ on Mac\nUse --electron-version to specify the version you downloaded.'); + log.warn( + '\nNo Internet Connection\nTo offline build, download electron from https://github.com/electron/electron/releases\nand place in ~/AppData/Local/electron/Cache/ on Windows,\n~/.cache/electron on Linux or ~/Library/Caches/electron/ on Mac\nUse --electron-version to specify the version you downloaded.', + ); } }); } - if (require.main === module) { program .version(packageJson.version) @@ -43,51 +44,153 @@ if (require.main === module) { program.out = appDir; }) .option('-n, --name ', 'app name') - .option('-p, --platform ', '\'osx\', \'mas\', \'linux\' or \'windows\'') - .option('-a, --arch ', '\'ia32\' or \'x64\' or \'armv7l\'') - .option('--app-version ', 'The release version of the application. Maps to the `ProductVersion` metadata property on Windows, and `CFBundleShortVersionString` on OS X.') - .option('--build-version ', 'The build version of the application. Maps to the `FileVersion` metadata property on Windows, and `CFBundleVersion` on OS X.') - .option('--app-copyright ', 'The human-readable copyright line for the app. Maps to the `LegalCopyright` metadata property on Windows, and `NSHumanReadableCopyright` on OS X') - .option('--win32metadata ', 'a JSON string of key/value pairs of application metadata (ProductName, InternalName, FileDescription) to embed into the executable (Windows only).', parseJson) - .option('-e, --electron-version ', 'electron version to package, without the \'v\', see https://github.com/atom/electron/releases') - .option('--no-overwrite', 'do not override output directory if it already exists, defaults to false') - .option('-c, --conceal', 'packages the source code within your app into an archive, defaults to false, see http://electron.atom.io/docs/v0.36.0/tutorial/application-packaging/') - .option('--counter', 'if the target app should use a persistent counter badge in the dock (macOS only), defaults to false') - .option('--bounce', 'if the the dock icon should bounce when counter increases (macOS only), defaults to false') - .option('-i, --icon ', 'the icon file to use as the icon for the app (should be a .png)') - .option('--width ', 'set window default width, defaults to 1280px', parseInt) - .option('--height ', 'set window default height, defaults to 800px', parseInt) - .option('--min-width ', 'set window minimum width, defaults to 0px', parseInt) - .option('--min-height ', 'set window minimum height, defaults to 0px', parseInt) - .option('--max-width ', 'set window maximum width, default is no limit', parseInt) - .option('--max-height ', 'set window maximum height, default is no limit', parseInt) + .option('-p, --platform ', "'osx', 'mas', 'linux' or 'windows'") + .option('-a, --arch ', "'ia32' or 'x64' or 'armv7l'") + .option( + '--app-version ', + 'The release version of the application. Maps to the `ProductVersion` metadata property on Windows, and `CFBundleShortVersionString` on OS X.', + ) + .option( + '--build-version ', + 'The build version of the application. Maps to the `FileVersion` metadata property on Windows, and `CFBundleVersion` on OS X.', + ) + .option( + '--app-copyright ', + 'The human-readable copyright line for the app. Maps to the `LegalCopyright` metadata property on Windows, and `NSHumanReadableCopyright` on OS X', + ) + .option( + '--win32metadata ', + 'a JSON string of key/value pairs of application metadata (ProductName, InternalName, FileDescription) to embed into the executable (Windows only).', + parseJson, + ) + .option( + '-e, --electron-version ', + "electron version to package, without the 'v', see https://github.com/atom/electron/releases", + ) + .option( + '--no-overwrite', + 'do not override output directory if it already exists, defaults to false', + ) + .option( + '-c, --conceal', + 'packages the source code within your app into an archive, defaults to false, see http://electron.atom.io/docs/v0.36.0/tutorial/application-packaging/', + ) + .option( + '--counter', + 'if the target app should use a persistent counter badge in the dock (macOS only), defaults to false', + ) + .option( + '--bounce', + 'if the the dock icon should bounce when counter increases (macOS only), defaults to false', + ) + .option( + '-i, --icon ', + 'the icon file to use as the icon for the app (should be a .png)', + ) + .option( + '--width ', + 'set window default width, defaults to 1280px', + parseInt, + ) + .option( + '--height ', + 'set window default height, defaults to 800px', + parseInt, + ) + .option( + '--min-width ', + 'set window minimum width, defaults to 0px', + parseInt, + ) + .option( + '--min-height ', + 'set window minimum height, defaults to 0px', + parseInt, + ) + .option( + '--max-width ', + 'set window maximum width, default is no limit', + parseInt, + ) + .option( + '--max-height ', + 'set window maximum height, default is no limit', + parseInt, + ) .option('--x ', 'set window x location', parseInt) .option('--y ', 'set window y location', parseInt) .option('-m, --show-menu-bar', 'set menu bar visible, defaults to false') - .option('-f, --fast-quit', 'quit app after window close (macOS only), defaults to false') + .option( + '-f, --fast-quit', + 'quit app after window close (macOS only), defaults to false', + ) .option('-u, --user-agent ', 'set the user agent string for the app') - .option('--honest', 'prevent the nativefied app from changing the user agent string to masquerade as a regular chrome browser') + .option( + '--honest', + 'prevent the nativefied app from changing the user agent string to masquerade as a regular chrome browser', + ) .option('--ignore-certificate', 'ignore certificate related errors') .option('--disable-gpu', 'disable hardware acceleration') - .option('--ignore-gpu-blacklist', 'allow WebGl apps to work on non supported graphics cards') + .option( + '--ignore-gpu-blacklist', + 'allow WebGl apps to work on non supported graphics cards', + ) .option('--enable-es3-apis', 'force activation of WebGl 2.0') - .option('--insecure', 'enable loading of insecure content, defaults to false') + .option( + '--insecure', + 'enable loading of insecure content, defaults to false', + ) .option('--flash', 'if flash should be enabled') - .option('--flash-path ', 'path to Chrome flash plugin, find it in `Chrome://plugins`') - .option('--disk-cache-size ', 'forces the maximum disk space (in bytes) to be used by the disk cache') - .option('--inject ', 'path to a CSS/JS file to be injected', collect, []) - .option('--full-screen', 'if the app should always be started in full screen') + .option( + '--flash-path ', + 'path to Chrome flash plugin, find it in `Chrome://plugins`', + ) + .option( + '--disk-cache-size ', + 'forces the maximum disk space (in bytes) to be used by the disk cache', + ) + .option( + '--inject ', + 'path to a CSS/JS file to be injected', + collect, + [], + ) + .option( + '--full-screen', + 'if the app should always be started in full screen', + ) .option('--maximize', 'if the app should always be started maximized') .option('--hide-window-frame', 'disable window frame and controls') .option('--verbose', 'if verbose logs should be displayed') .option('--disable-context-menu', 'disable the context menu') .option('--disable-dev-tools', 'disable developer tools') - .option('--zoom ', 'default zoom factor to use when the app is opened, defaults to 1.0', parseFloat) - .option('--internal-urls ', 'regular expression of URLs to consider "internal"; all other URLs will be opened in an external browser. (default: URLs on same second-level domain as app)') - .option('--crash-reporter ', 'remote server URL to send crash reports') - .option('--single-instance', 'allow only a single instance of the application') - .option('--processEnvs ', 'a JSON string of key/value pairs to be set as environment variables before any browser windows are opened.', getProcessEnvs) - .option('--file-download-options ', 'a JSON string of key/value pairs to be set as file download options. See https://github.com/sindresorhus/electron-dl for available options.', parseJson) + .option( + '--zoom ', + 'default zoom factor to use when the app is opened, defaults to 1.0', + parseFloat, + ) + .option( + '--internal-urls ', + 'regular expression of URLs to consider "internal"; all other URLs will be opened in an external browser. (default: URLs on same second-level domain as app)', + ) + .option( + '--crash-reporter ', + 'remote server URL to send crash reports', + ) + .option( + '--single-instance', + 'allow only a single instance of the application', + ) + .option( + '--processEnvs ', + 'a JSON string of key/value pairs to be set as environment variables before any browser windows are opened.', + getProcessEnvs, + ) + .option( + '--file-download-options ', + 'a JSON string of key/value pairs to be set as file download options. See https://github.com/sindresorhus/electron-dl for available options.', + parseJson, + ) .option('--tray', 'allow app to stay in system tray') .option('--basic-auth-username ', 'basic http(s) auth username') .option('--basic-auth-password ', 'basic http(s) auth password') diff --git a/src/helpers/convertToIcns.js b/src/helpers/convertToIcns.js index 439820d..de739d6 100644 --- a/src/helpers/convertToIcns.js +++ b/src/helpers/convertToIcns.js @@ -26,22 +26,29 @@ function convertToIcns(pngSrc, icnsDest, callback) { return; } - shell.exec(`${PNG_TO_ICNS_BIN_PATH} ${pngSrc} ${icnsDest}`, { silent: true }, (exitCode, stdOut, stdError) => { - if (stdOut.includes('icon.iconset:error') || exitCode) { - if (exitCode) { - callback({ - stdOut, - stdError, - }, pngSrc); + shell.exec( + `${PNG_TO_ICNS_BIN_PATH} ${pngSrc} ${icnsDest}`, + { silent: true }, + (exitCode, stdOut, stdError) => { + if (stdOut.includes('icon.iconset:error') || exitCode) { + if (exitCode) { + callback( + { + stdOut, + stdError, + }, + pngSrc, + ); + return; + } + + callback(stdOut, pngSrc); return; } - callback(stdOut, pngSrc); - return; - } - - callback(null, icnsDest); - }); + callback(null, icnsDest); + }, + ); } /** diff --git a/src/helpers/helpers.js b/src/helpers/helpers.js index ac7e1af..ba525b8 100644 --- a/src/helpers/helpers.js +++ b/src/helpers/helpers.js @@ -12,9 +12,10 @@ function isWindows() { } function downloadFile(fileUrl) { - return axios.get(fileUrl, { - responseType: 'arraybuffer', - }) + return axios + .get(fileUrl, { + responseType: 'arraybuffer', + }) .then((response) => { if (!response.data) { return null; @@ -55,7 +56,9 @@ function allowedIconFormats(platform) { formats.push('.ico'); break; default: - throw new Error(`function allowedIconFormats error: Unknown platform ${platform}`); + throw new Error( + `function allowedIconFormats error: Unknown platform ${platform}`, + ); } return formats; } @@ -89,7 +92,9 @@ function allowedIconFormats(platform) { } break; default: - throw new Error(`function allowedIconFormats error: Unknown platform ${platform}`); + throw new Error( + `function allowedIconFormats error: Unknown platform ${platform}`, + ); } return formats; } diff --git a/src/helpers/iconShellHelpers.js b/src/helpers/iconShellHelpers.js index 3a8cfa4..95ac645 100644 --- a/src/helpers/iconShellHelpers.js +++ b/src/helpers/iconShellHelpers.js @@ -27,18 +27,22 @@ function iconShellHelper(shellScriptPath, icoSrc, dest) { return; } - shell.exec(`${shellScriptPath} ${icoSrc} ${dest}`, { silent: true }, (exitCode, stdOut, stdError) => { - if (exitCode) { - // eslint-disable-next-line prefer-promise-reject-errors - reject({ - stdOut, - stdError, - }); - return; - } + shell.exec( + `${shellScriptPath} ${icoSrc} ${dest}`, + { silent: true }, + (exitCode, stdOut, stdError) => { + if (exitCode) { + // eslint-disable-next-line prefer-promise-reject-errors + reject({ + stdOut, + stdError, + }); + return; + } - resolve(dest); - }); + resolve(dest); + }, + ); }); } @@ -54,22 +58,40 @@ function getTmpDirPath() { */ function singleIco(icoSrc) { - return iconShellHelper(SCRIPT_PATHS.singleIco, icoSrc, `${getTmpDirPath()}/icon.ico`); + return iconShellHelper( + SCRIPT_PATHS.singleIco, + icoSrc, + `${getTmpDirPath()}/icon.ico`, + ); } function convertToPng(icoSrc) { - return iconShellHelper(SCRIPT_PATHS.convertToPng, icoSrc, `${getTmpDirPath()}/icon.png`); + return iconShellHelper( + SCRIPT_PATHS.convertToPng, + icoSrc, + `${getTmpDirPath()}/icon.png`, + ); } function convertToIco(icoSrc) { - return iconShellHelper(SCRIPT_PATHS.convertToIco, icoSrc, `${getTmpDirPath()}/icon.ico`); + return iconShellHelper( + SCRIPT_PATHS.convertToIco, + icoSrc, + `${getTmpDirPath()}/icon.ico`, + ); } function convertToIcns(icoSrc) { if (!isOSX()) { - return new Promise((resolve, reject) => reject(new Error('OSX is required to convert to a .icns icon'))); + return new Promise((resolve, reject) => + reject(new Error('OSX is required to convert to a .icns icon')), + ); } - return iconShellHelper(SCRIPT_PATHS.convertToIcns, icoSrc, `${getTmpDirPath()}/icon.icns`); + return iconShellHelper( + SCRIPT_PATHS.convertToIcns, + icoSrc, + `${getTmpDirPath()}/icon.icns`, + ); } export default { diff --git a/src/infer/inferIcon.js b/src/infer/inferIcon.js index d7cbe9b..638e04c 100644 --- a/src/infer/inferIcon.js +++ b/src/infer/inferIcon.js @@ -25,31 +25,30 @@ function getMaxMatchScore(iconWithScores) { */ function getMatchingIcons(iconsWithScores, maxScore) { return iconsWithScores - .filter(item => item.score === maxScore) - .map(item => Object.assign({}, item, { ext: path.extname(item.url) })); + .filter((item) => item.score === maxScore) + .map((item) => Object.assign({}, item, { ext: path.extname(item.url) })); } function mapIconWithMatchScore(fileIndex, targetUrl) { const normalisedTargetUrl = targetUrl.toLowerCase(); - return fileIndex - .map((item) => { - const itemWords = item.name.split(GITCLOUD_SPACE_DELIMITER); - const score = itemWords.reduce((currentScore, word) => { - if (normalisedTargetUrl.includes(word)) { - return currentScore + 1; - } - return currentScore; - }, 0); + return fileIndex.map((item) => { + const itemWords = item.name.split(GITCLOUD_SPACE_DELIMITER); + const score = itemWords.reduce((currentScore, word) => { + if (normalisedTargetUrl.includes(word)) { + return currentScore + 1; + } + return currentScore; + }, 0); - return Object.assign({}, item, { score }); - }); + return Object.assign({}, item, { score }); + }); } function inferIconFromStore(targetUrl, platform) { const allowedFormats = new Set(allowedIconFormats(platform)); - return gitCloud('https://jiahaog.github.io/nativefier-icons/') - .then((fileIndex) => { + return gitCloud('https://jiahaog.github.io/nativefier-icons/').then( + (fileIndex) => { const iconWithScores = mapIconWithMatchScore(fileIndex, targetUrl); const maxScore = getMaxMatchScore(iconWithScores); @@ -58,7 +57,9 @@ function inferIconFromStore(targetUrl, platform) { } const iconsMatchingScore = getMatchingIcons(iconWithScores, maxScore); - const iconsMatchingExt = iconsMatchingScore.filter(icon => allowedFormats.has(icon.ext)); + const iconsMatchingExt = iconsMatchingScore.filter((icon) => + allowedFormats.has(icon.ext), + ); const matchingIcon = iconsMatchingExt[0]; const iconUrl = matchingIcon && matchingIcon.url; @@ -66,7 +67,8 @@ function inferIconFromStore(targetUrl, platform) { return null; } return downloadFile(iconUrl); - }); + }, + ); } function writeFilePromise(outPath, data) { @@ -88,15 +90,14 @@ function inferFromPage(targetUrl, platform, outDir) { } // todo might want to pass list of preferences instead - return pageIcon(targetUrl, { ext: preferredExt }) - .then((icon) => { - if (!icon) { - return null; - } + return pageIcon(targetUrl, { ext: preferredExt }).then((icon) => { + if (!icon) { + return null; + } - const outfilePath = path.join(outDir, `/icon${icon.ext}`); - return writeFilePromise(outfilePath, icon.data); - }); + const outfilePath = path.join(outDir, `/icon${icon.ext}`); + return writeFilePromise(outfilePath, icon.data); + }); } /** @@ -106,15 +107,14 @@ function inferFromPage(targetUrl, platform, outDir) { * @param {string} outDir */ function inferIconFromUrlToPath(targetUrl, platform, outDir) { - return inferIconFromStore(targetUrl, platform) - .then((icon) => { - if (!icon) { - return inferFromPage(targetUrl, platform, outDir); - } + return inferIconFromStore(targetUrl, platform).then((icon) => { + if (!icon) { + return inferFromPage(targetUrl, platform, outDir); + } - const outfilePath = path.join(outDir, `/icon${icon.ext}`); - return writeFilePromise(outfilePath, icon.data); - }); + const outfilePath = path.join(outDir, `/icon${icon.ext}`); + return writeFilePromise(outfilePath, icon.data); + }); } /** diff --git a/src/infer/inferOs.js b/src/infer/inferOs.js index 0bbf66b..7f639da 100644 --- a/src/infer/inferOs.js +++ b/src/infer/inferOs.js @@ -2,7 +2,12 @@ import os from 'os'; function inferPlatform() { const platform = os.platform(); - if ((platform === 'darwin' || platform === 'mas') || platform === 'win32' || platform === 'linux') { + if ( + platform === 'darwin' || + platform === 'mas' || + platform === 'win32' || + platform === 'linux' + ) { return platform; } diff --git a/src/infer/inferTitle.js b/src/infer/inferTitle.js index d20a397..fc3a212 100644 --- a/src/infer/inferTitle.js +++ b/src/infer/inferTitle.js @@ -1,7 +1,8 @@ import axios from 'axios'; import cheerio from 'cheerio'; -const USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.1 Safari/537.36'; +const USER_AGENT = + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.1 Safari/537.36'; function inferTitle(url) { const options = { @@ -15,7 +16,10 @@ function inferTitle(url) { return axios(options).then(({ data }) => { const $ = cheerio.load(data); - return $('title').first().text().replace(/\//g, ''); + return $('title') + .first() + .text() + .replace(/\//g, ''); }); } diff --git a/src/infer/inferUserAgent.js b/src/infer/inferUserAgent.js index 09be621..e07dc35 100644 --- a/src/infer/inferUserAgent.js +++ b/src/infer/inferUserAgent.js @@ -5,25 +5,29 @@ import log from 'loglevel'; const ELECTRON_VERSIONS_URL = 'https://atom.io/download/atom-shell/index.json'; const DEFAULT_CHROME_VERSION = '58.0.3029.110'; -function getChromeVersionForElectronVersion(electronVersion, url = ELECTRON_VERSIONS_URL) { - return axios.get(url, { timeout: 5000 }) - .then((response) => { - if (response.status !== 200) { - throw new Error(`Bad request: Status code ${response.status}`); - } +function getChromeVersionForElectronVersion( + electronVersion, + url = ELECTRON_VERSIONS_URL, +) { + return axios.get(url, { timeout: 5000 }).then((response) => { + if (response.status !== 200) { + throw new Error(`Bad request: Status code ${response.status}`); + } - const { data } = response; - const electronVersionToChromeVersion = _.zipObject( - data.map(d => d.version), - data.map(d => d.chrome), + const { data } = response; + const electronVersionToChromeVersion = _.zipObject( + data.map((d) => d.version), + data.map((d) => d.chrome), + ); + + if (!(electronVersion in electronVersionToChromeVersion)) { + throw new Error( + `Electron version '${electronVersion}' not found in retrieved version list!`, ); + } - if (!(electronVersion in electronVersionToChromeVersion)) { - throw new Error(`Electron version '${electronVersion}' not found in retrieved version list!`); - } - - return electronVersionToChromeVersion[electronVersion]; - }); + return electronVersionToChromeVersion[electronVersion]; + }); } export function getUserAgentString(chromeVersion, platform) { @@ -40,16 +44,24 @@ export function getUserAgentString(chromeVersion, platform) { userAgent = `Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/${chromeVersion} Safari/537.36`; break; default: - throw new Error('Error invalid platform specified to getUserAgentString()'); + throw new Error( + 'Error invalid platform specified to getUserAgentString()', + ); } return userAgent; } -function inferUserAgent(electronVersion, platform, url = ELECTRON_VERSIONS_URL) { +function inferUserAgent( + electronVersion, + platform, + url = ELECTRON_VERSIONS_URL, +) { return getChromeVersionForElectronVersion(electronVersion, url) - .then(chromeVersion => getUserAgentString(chromeVersion, platform)) + .then((chromeVersion) => getUserAgentString(chromeVersion, platform)) .catch(() => { - log.warn(`Unable to infer chrome version for user agent, using ${DEFAULT_CHROME_VERSION}`); + log.warn( + `Unable to infer chrome version for user agent, using ${DEFAULT_CHROME_VERSION}`, + ); return getUserAgentString(DEFAULT_CHROME_VERSION, platform); }); } diff --git a/src/infer/inferUserAgent.test.js b/src/infer/inferUserAgent.test.js index c847612..599ea8b 100644 --- a/src/infer/inferUserAgent.test.js +++ b/src/infer/inferUserAgent.test.js @@ -20,7 +20,9 @@ function testPlatform(platform) { describe('Infer User Agent', () => { test('Can infer userAgent for all platforms', (done) => { - const testPromises = _.keys(TEST_RESULT).map(platform => testPlatform(platform)); + const testPromises = _.keys(TEST_RESULT).map((platform) => + testPlatform(platform), + ); Promise.all(testPromises) .then(() => { done(); @@ -36,7 +38,9 @@ describe('Infer User Agent', () => { const TIMEOUT_URL = 'http://www.google.com:81/'; inferUserAgent('1.6.7', 'darwin', TIMEOUT_URL) .then((userAgent) => { - expect(userAgent).toBe('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'); + expect(userAgent).toBe( + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36', + ); done(); }) .catch(done); diff --git a/src/options/asyncConfig.js b/src/options/asyncConfig.js index a9f1c06..597ea84 100644 --- a/src/options/asyncConfig.js +++ b/src/options/asyncConfig.js @@ -1,7 +1,10 @@ import fields from './fields'; function resultArrayToObject(fieldResults) { - return fieldResults.reduce((accumulator, value) => Object.assign({}, accumulator, value), {}); + return fieldResults.reduce( + (accumulator, value) => Object.assign({}, accumulator, value), + {}, + ); } function inferredOptions(oldOptions, fieldResults) { @@ -11,8 +14,9 @@ function inferredOptions(oldOptions, fieldResults) { // Takes the options object and infers new values // which may need async work -export default function (options) { +export default function(options) { const tasks = fields(options); - return Promise.all(tasks) - .then(fieldResults => inferredOptions(options, fieldResults)); + return Promise.all(tasks).then((fieldResults) => + inferredOptions(options, fieldResults), + ); } diff --git a/src/options/asyncConfig.test.js b/src/options/asyncConfig.test.js index de0d108..1ab906f 100644 --- a/src/options/asyncConfig.test.js +++ b/src/options/asyncConfig.test.js @@ -3,9 +3,11 @@ import fields from './fields'; jest.mock('./fields'); -fields.mockImplementation(() => [Promise.resolve({ - someField: 'newValue', -})]); +fields.mockImplementation(() => [ + Promise.resolve({ + someField: 'newValue', + }), +]); test('it should merge the result of the promise', () => { const param = { another: 'field', someField: 'oldValue' }; @@ -15,4 +17,3 @@ test('it should merge the result of the promise', () => { expect(result).toEqual(expected); }); }); - diff --git a/src/options/fields/icon.js b/src/options/fields/icon.js index 5b39c96..577cc75 100644 --- a/src/options/fields/icon.js +++ b/src/options/fields/icon.js @@ -1,15 +1,14 @@ import log from 'loglevel'; import { inferIcon } from './../../infer'; -export default function ({ icon, targetUrl, platform }) { +export default function({ icon, targetUrl, platform }) { // Icon is the path to the icon if (icon) { return Promise.resolve(icon); } - return inferIcon(targetUrl, platform) - .catch((error) => { - log.warn('Cannot automatically retrieve the app icon:', error); - return null; - }); + return inferIcon(targetUrl, platform).catch((error) => { + log.warn('Cannot automatically retrieve the app icon:', error); + return null; + }); } diff --git a/src/options/fields/icon.test.js b/src/options/fields/icon.test.js index 11ff6f0..50c5d77 100644 --- a/src/options/fields/icon.test.js +++ b/src/options/fields/icon.test.js @@ -29,12 +29,17 @@ describe('when the icon parameter is not passed', () => { describe('when inferIcon resolves with an error', () => { test('it should handle the error', () => { - inferIcon.mockImplementationOnce(() => Promise.reject(new Error('some error'))); + inferIcon.mockImplementationOnce(() => + Promise.reject(new Error('some error')), + ); const params = { targetUrl: 'some url', platform: 'mac' }; return icon(params).then((result) => { expect(result).toBe(null); - expect(inferIcon).toHaveBeenCalledWith(params.targetUrl, params.platform); + expect(inferIcon).toHaveBeenCalledWith( + params.targetUrl, + params.platform, + ); expect(log.warn).toHaveBeenCalledTimes(1); }); }); diff --git a/src/options/fields/index.js b/src/options/fields/index.js index 7956206..e8cd312 100644 --- a/src/options/fields/index.js +++ b/src/options/fields/index.js @@ -2,28 +2,31 @@ import icon from './icon'; import userAgent from './userAgent'; import name from './name'; -const fields = [{ - field: 'userAgent', - task: userAgent, -}, { - field: 'icon', - task: icon, -}, { - field: 'name', - task: name, -}]; +const fields = [ + { + field: 'userAgent', + task: userAgent, + }, + { + field: 'icon', + task: icon, + }, + { + field: 'name', + task: name, + }, +]; // Modifies the result of each promise from a scalar // value to a object containing its fieldname function wrap(fieldName, promise, args) { - return promise(args) - .then(result => ({ - [fieldName]: result, - })); + return promise(args).then((result) => ({ + [fieldName]: result, + })); } // Returns a list of promises which will all resolve // with the following result: {[fieldName]: fieldvalue} -export default function (options) { +export default function(options) { return fields.map(({ field, task }) => wrap(field, task, options)); } diff --git a/src/options/fields/index.test.js b/src/options/fields/index.test.js index 36f0926..045857e 100644 --- a/src/options/fields/index.test.js +++ b/src/options/fields/index.test.js @@ -19,4 +19,3 @@ test('it should return a list of promises', () => { expect(value).toBeInstanceOf(Promise); }); }); - diff --git a/src/options/fields/name.js b/src/options/fields/name.js index eca888e..b3e9673 100644 --- a/src/options/fields/name.js +++ b/src/options/fields/name.js @@ -10,14 +10,17 @@ function tryToInferName({ name, targetUrl }) { } return inferTitle(targetUrl) - .then(pageTitle => (pageTitle || DEFAULT_APP_NAME)) + .then((pageTitle) => pageTitle || DEFAULT_APP_NAME) .catch((error) => { - log.warn(`Unable to automatically determine app name, falling back to '${DEFAULT_APP_NAME}'. Reason: ${error}`); + log.warn( + `Unable to automatically determine app name, falling back to '${DEFAULT_APP_NAME}'. Reason: ${error}`, + ); return DEFAULT_APP_NAME; }); } -export default function ({ platform, name, targetUrl }) { - return tryToInferName({ name, targetUrl }) - .then(result => sanitizeFilename(platform, result)); +export default function({ platform, name, targetUrl }) { + return tryToInferName({ name, targetUrl }).then((result) => + sanitizeFilename(platform, result), + ); } diff --git a/src/options/fields/name.test.js b/src/options/fields/name.test.js index e4913e0..b668572 100644 --- a/src/options/fields/name.test.js +++ b/src/options/fields/name.test.js @@ -14,14 +14,16 @@ const mockedResult = 'mock name'; describe('well formed name parameters', () => { const params = { name: 'appname', platform: 'something' }; - test('it should not call inferTitle', () => name(params).then((result) => { - expect(inferTitle).toHaveBeenCalledTimes(0); - expect(result).toBe(params.name); - })); + test('it should not call inferTitle', () => + name(params).then((result) => { + expect(inferTitle).toHaveBeenCalledTimes(0); + expect(result).toBe(params.name); + })); - test('it should call sanitize filename', () => name(params).then((result) => { - expect(sanitizeFilename).toHaveBeenCalledWith(params.platform, result); - })); + test('it should call sanitize filename', () => + name(params).then((result) => { + expect(sanitizeFilename).toHaveBeenCalledWith(params.platform, result); + })); }); describe('bad name parameters', () => { @@ -31,9 +33,10 @@ describe('bad name parameters', () => { const params = { targetUrl: 'some url' }; describe('when the name is undefined', () => { - test('it should call inferTitle', () => name(params).then(() => { - expect(inferTitle).toHaveBeenCalledWith(params.targetUrl); - })); + test('it should call inferTitle', () => + name(params).then(() => { + expect(inferTitle).toHaveBeenCalledWith(params.targetUrl); + })); }); describe('when the name is an empty string', () => { @@ -46,9 +49,10 @@ describe('bad name parameters', () => { }); }); - test('it should call sanitize filename', () => name(params).then((result) => { - expect(sanitizeFilename).toHaveBeenCalledWith(params.platform, result); - })); + test('it should call sanitize filename', () => + name(params).then((result) => { + expect(sanitizeFilename).toHaveBeenCalledWith(params.platform, result); + })); }); describe('handling inferTitle results', () => { @@ -75,7 +79,9 @@ describe('handling inferTitle results', () => { describe('when inferTitle resolves with an error', () => { test('it should return the default app name', () => { - inferTitle.mockImplementationOnce(() => Promise.reject(new Error('some error'))); + inferTitle.mockImplementationOnce(() => + Promise.reject(new Error('some error')), + ); return name(params).then((result) => { expect(result).toBe(DEFAULT_APP_NAME); diff --git a/src/options/fields/userAgent.js b/src/options/fields/userAgent.js index 5eefc2a..6a26aaf 100644 --- a/src/options/fields/userAgent.js +++ b/src/options/fields/userAgent.js @@ -1,6 +1,6 @@ import { inferUserAgent } from './../../infer'; -export default function ({ userAgent, electronVersion, platform }) { +export default function({ userAgent, electronVersion, platform }) { if (userAgent) { return Promise.resolve(userAgent); } diff --git a/src/options/fields/userAgent.test.js b/src/options/fields/userAgent.test.js index effe3f3..03b3a55 100644 --- a/src/options/fields/userAgent.test.js +++ b/src/options/fields/userAgent.test.js @@ -13,6 +13,8 @@ test('when a userAgent parameter is passed', () => { test('no userAgent parameter is passed', () => { const params = { electronVersion: '123', platform: 'mac' }; userAgent(params); - expect(inferUserAgent).toHaveBeenCalledWith(params.electronVersion, params.platform); + expect(inferUserAgent).toHaveBeenCalledWith( + params.electronVersion, + params.platform, + ); }); - diff --git a/src/options/normalizeUrl.test.js b/src/options/normalizeUrl.test.js index 08d9425..7c36356 100644 --- a/src/options/normalizeUrl.test.js +++ b/src/options/normalizeUrl.test.js @@ -1,7 +1,9 @@ import normalizeUrl from './normalizeUrl'; test("a proper URL shouldn't be mangled", () => { - expect(normalizeUrl('http://www.google.com')).toEqual('http://www.google.com'); + expect(normalizeUrl('http://www.google.com')).toEqual( + 'http://www.google.com', + ); }); test('missing protocol should default to http', () => { @@ -9,5 +11,7 @@ test('missing protocol should default to http', () => { }); test("a proper URL shouldn't be mangled", () => { - expect(() => { normalizeUrl('http://ssddfoo bar'); }).toThrow('Your Url: "http://ssddfoo bar" is invalid!'); + expect(() => { + normalizeUrl('http://ssddfoo bar'); + }).toThrow('Your Url: "http://ssddfoo bar" is invalid!'); }); diff --git a/src/options/optionsMain.js b/src/options/optionsMain.js index e599179..cef542d 100644 --- a/src/options/optionsMain.js +++ b/src/options/optionsMain.js @@ -13,7 +13,7 @@ const { inferPlatform, inferArch } = inferOs; * @param {Object} inpOptions * @returns {Promise} */ -export default function (inpOptions) { +export default function(inpOptions) { const options = { dir: PLACEHOLDER_APP_DIR, name: inpOptions.name, @@ -93,7 +93,10 @@ export default function (inpOptions) { options.platform = 'win32'; } - if (options.platform.toLowerCase() === 'osx' || options.platform.toLowerCase() === 'mac') { + if ( + options.platform.toLowerCase() === 'osx' || + options.platform.toLowerCase() === 'mac' + ) { options.platform = 'darwin'; } diff --git a/src/utils/sanitizeFilename.js b/src/utils/sanitizeFilename.js index 5f0068f..36c8e16 100644 --- a/src/utils/sanitizeFilename.js +++ b/src/utils/sanitizeFilename.js @@ -2,7 +2,7 @@ import _ from 'lodash'; import sanitizeFilenameLib from 'sanitize-filename'; import { DEFAULT_APP_NAME } from './../constants'; -export default function (platform, str) { +export default function(platform, str) { let result = sanitizeFilenameLib(str); // remove all non ascii or use default app name diff --git a/src/utils/sanitizeFilename.test.js b/src/utils/sanitizeFilename.test.js index 8d9d859..73f04bc 100644 --- a/src/utils/sanitizeFilename.test.js +++ b/src/utils/sanitizeFilename.test.js @@ -3,7 +3,7 @@ import sanitizeFilename from './sanitizeFilename'; import { DEFAULT_APP_NAME } from './../constants'; jest.mock('sanitize-filename'); -sanitizeFilenameLib.mockImplementation(str => str); +sanitizeFilenameLib.mockImplementation((str) => str); test('it should call the sanitize-filename npm module', () => { const param = 'abc';