2
2
mirror of https://github.com/Llewellynvdm/nativefier.git synced 2024-12-22 10:08:55 +00:00

Integrate prettier

This commit is contained in:
Goh Jia Hao 2018-05-24 00:02:44 -07:00
parent 949dcfadd8
commit 95fc46d38d
41 changed files with 632 additions and 347 deletions

View File

@ -13,7 +13,7 @@ insert_final_newline = true
[*.{js,py}] [*.{js,py}]
charset = utf-8 charset = utf-8
indent_style = space indent_style = space
indent_size = 4 indent_size = 2
# 2 space indentation # 2 space indentation
[*.{html,css,less,scss,yml,json}] [*.{html,css,less,scss,yml,json}]

View File

@ -1,11 +1,15 @@
extends: airbnb-base extends:
- airbnb-base
- prettier
env: env:
# TODO: find out how to turn this on only for src/**/*.test.js files # TODO: find out how to turn this on only for src/**/*.test.js files
jest: true jest: true
plugins: plugins:
- import - import
- prettier
rules: rules:
# TODO: Remove this when we have shifted away from the async package # TODO: Remove this when we have shifted away from the async package
no-shadow: 'warn' no-shadow: 'warn'
# Gulpfiles and tests use dev dependencies # Gulpfiles and tests use dev dependencies
import/no-extraneous-dependencies: ['error', { devDependencies: ['gulpfile.babel.js', 'gulp/**/**.js', 'test/**/**.js']}] import/no-extraneous-dependencies: ['error', { devDependencies: ['gulpfile.babel.js', 'gulp/**/**.js', 'test/**/**.js']}]
prettier/prettier: "error"

3
.prettierrc.yaml Normal file
View File

@ -0,0 +1,3 @@
arrowParens: always
singleQuote: true
trailingComma: all

View File

@ -8,7 +8,9 @@ function createLoginWindow(loginCallback) {
frame: false, frame: false,
resizable: 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) => { ipcMain.once('login-message', (event, usernameAndPassword) => {
loginCallback(usernameAndPassword[0], usernameAndPassword[1]); loginCallback(usernameAndPassword[0], usernameAndPassword[1]);

View File

@ -7,7 +7,12 @@ import createMenu from './../menu/menu';
import initContextMenu from './../contextMenu/contextMenu'; import initContextMenu from './../contextMenu/contextMenu';
const { const {
isOSX, linkIsInternal, getCssToInject, shouldInjectCss, getAppIcon, nativeTabsSupported, isOSX,
linkIsInternal,
getCssToInject,
shouldInjectCss,
getAppIcon,
nativeTabsSupported,
} = helpers; } = helpers;
const ZOOM_INTERVAL = 0.1; const ZOOM_INTERVAL = 0.1;
@ -37,7 +42,10 @@ function maybeInjectCss(browserWindow) {
browserWindow.webContents.on('did-finish-load', () => { browserWindow.webContents.on('did-finish-load', () => {
// remove the injection of css the moment the page is loaded // 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 // on every page navigation inject the css
@ -48,7 +56,6 @@ function maybeInjectCss(browserWindow) {
}); });
} }
/** /**
* *
* @param {{}} inpOptions AppArgs from nativefier.json * @param {{}} inpOptions AppArgs from nativefier.json
@ -78,7 +85,9 @@ function createMainWindow(inpOptions, onAppQuit, setDockBadge) {
}, },
}; };
const mainWindow = new BrowserWindow(Object.assign({ const mainWindow = new BrowserWindow(
Object.assign(
{
frame: !options.hideWindowFrame, frame: !options.hideWindowFrame,
width: mainWindowState.width, width: mainWindowState.width,
height: mainWindowState.height, height: mainWindowState.height,
@ -95,7 +104,10 @@ function createMainWindow(inpOptions, onAppQuit, setDockBadge) {
fullscreen: options.fullScreen || undefined, fullscreen: options.fullScreen || undefined,
// Whether the window should always stay on top of other windows. Default is false. // Whether the window should always stay on top of other windows. Default is false.
alwaysOnTop: options.alwaysOnTop, alwaysOnTop: options.alwaysOnTop,
}, DEFAULT_WINDOW_OPTIONS)); },
DEFAULT_WINDOW_OPTIONS,
),
);
mainWindowState.manage(mainWindow); mainWindowState.manage(mainWindow);
@ -103,12 +115,17 @@ function createMainWindow(inpOptions, onAppQuit, setDockBadge) {
if (options.maximize) { if (options.maximize) {
mainWindow.maximize(); mainWindow.maximize();
options.maximize = undefined; 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 withFocusedWindow = (block) => {
const focusedWindow = BrowserWindow.getFocusedWindow(); const focusedWindow = BrowserWindow.getFocusedWindow();
if (focusedWindow) { block(focusedWindow); } if (focusedWindow) {
block(focusedWindow);
}
}; };
const adjustWindowZoom = (window, adjustment) => { const adjustWindowZoom = (window, adjustment) => {
@ -118,11 +135,15 @@ function createMainWindow(inpOptions, onAppQuit, setDockBadge) {
}; };
const onZoomIn = () => { const onZoomIn = () => {
withFocusedWindow(focusedWindow => adjustWindowZoom(focusedWindow, ZOOM_INTERVAL)); withFocusedWindow((focusedWindow) =>
adjustWindowZoom(focusedWindow, ZOOM_INTERVAL),
);
}; };
const onZoomOut = () => { const onZoomOut = () => {
withFocusedWindow(focusedWindow => adjustWindowZoom(focusedWindow, -ZOOM_INTERVAL)); withFocusedWindow((focusedWindow) =>
adjustWindowZoom(focusedWindow, -ZOOM_INTERVAL),
);
}; };
const onZoomReset = () => { const onZoomReset = () => {
@ -132,13 +153,17 @@ function createMainWindow(inpOptions, onAppQuit, setDockBadge) {
}; };
const clearAppData = () => { const clearAppData = () => {
dialog.showMessageBox(mainWindow, { dialog.showMessageBox(
mainWindow,
{
type: 'warning', type: 'warning',
buttons: ['Yes', 'Cancel'], buttons: ['Yes', 'Cancel'],
defaultId: 1, defaultId: 1,
title: 'Clear cache confirmation', title: 'Clear cache confirmation',
message: 'This will clear all data (cookies, local storage etc) from this app. Are you sure you wish to proceed?', message:
}, (response) => { 'This will clear all data (cookies, local storage etc) from this app. Are you sure you wish to proceed?',
},
(response) => {
if (response !== 0) { if (response !== 0) {
return; return;
} }
@ -148,7 +173,8 @@ function createMainWindow(inpOptions, onAppQuit, setDockBadge) {
mainWindow.loadURL(options.targetUrl); mainWindow.loadURL(options.targetUrl);
}); });
}); });
}); },
);
}; };
const onGoBack = () => { const onGoBack = () => {
@ -236,7 +262,10 @@ function createMainWindow(inpOptions, onAppQuit, setDockBadge) {
createMenu(menuOptions); createMenu(menuOptions);
if (!options.disableContextMenu) { if (!options.disableContextMenu) {
initContextMenu(createNewWindow, nativeTabsSupported() ? createNewTab : undefined); initContextMenu(
createNewWindow,
nativeTabsSupported() ? createNewTab : undefined,
);
} }
if (options.userAgent) { if (options.userAgent) {
@ -280,7 +309,10 @@ function createMainWindow(inpOptions, onAppQuit, setDockBadge) {
mainWindow.moveTabToNewWindow(); mainWindow.moveTabToNewWindow();
} }
mainWindow.setFullScreen(false); 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); maybeHideWindow(mainWindow, event, options.fastQuit, options.tray);
}); });

View File

@ -29,9 +29,10 @@ function createMenu({
if (Menu.getApplicationMenu()) { if (Menu.getApplicationMenu()) {
return; return;
} }
const zoomResetLabel = (zoomBuildTimeValue === 1.0) ? const zoomResetLabel =
'Reset Zoom' : zoomBuildTimeValue === 1.0
`Reset Zoom (to ${zoomBuildTimeValue * 100}%, set at build time)`; ? 'Reset Zoom'
: `Reset Zoom (to ${zoomBuildTimeValue * 100}%, set at build time)`;
const template = [ const template = [
{ {

View File

@ -1,8 +1,6 @@
import helpers from './../../helpers/helpers'; import helpers from './../../helpers/helpers';
const { const { app, Tray, Menu, ipcMain, nativeImage } = require('electron');
app, Tray, Menu, ipcMain, nativeImage,
} = require('electron');
const { getAppIcon } = helpers; const { getAppIcon } = helpers;

View File

@ -47,7 +47,7 @@ function findSync(pattern, basePath, findDir) {
matches.push(childPath); matches.push(childPath);
} }
}); });
}(basePath)); })(basePath);
return matches; return matches;
} }
@ -56,11 +56,18 @@ function linuxMatch() {
} }
function windowsMatch() { 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() { function darwinMatch() {
return findSync(/PepperFlashPlayer.plugin/, '/Applications/Google Chrome.app/', true)[0]; return findSync(
/PepperFlashPlayer.plugin/,
'/Applications/Google Chrome.app/',
true,
)[0];
} }
function inferFlash() { function inferFlash() {

View File

@ -55,11 +55,17 @@ if (appArgs.diskCacheSize) {
} }
if (appArgs.basicAuthUsername) { if (appArgs.basicAuthUsername) {
app.commandLine.appendSwitch('basic-auth-username', appArgs.basicAuthUsername); app.commandLine.appendSwitch(
'basic-auth-username',
appArgs.basicAuthUsername,
);
} }
if (appArgs.basicAuthPassword) { 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 // do nothing for setDockBadge if not OSX
@ -126,7 +132,10 @@ app.on('login', (event, webContents, request, authInfo, callback) => {
// for http authentication // for http authentication
event.preventDefault(); event.preventDefault();
if (appArgs.basicAuthUsername !== null && appArgs.basicAuthPassword !== null) { if (
appArgs.basicAuthUsername !== null &&
appArgs.basicAuthPassword !== null
) {
callback(appArgs.basicAuthUsername, appArgs.basicAuthPassword); callback(appArgs.basicAuthUsername, appArgs.basicAuthPassword);
} else { } else {
createLoginWindow(callback); createLoginWindow(callback);
@ -137,9 +146,12 @@ if (appArgs.singleInstance) {
const shouldQuit = app.makeSingleInstance(() => { const shouldQuit = app.makeSingleInstance(() => {
// Someone tried to run a second instance, we should focus our window. // Someone tried to run a second instance, we should focus our window.
if (mainWindow) { if (mainWindow) {
if (!mainWindow.isVisible()) { // tray if (!mainWindow.isVisible()) {
// tray
mainWindow.show(); mainWindow.show();
} if (mainWindow.isMinimized()) { // minimized }
if (mainWindow.isMinimized()) {
// minimized
mainWindow.restore(); mainWindow.restore();
} }
mainWindow.focus(); mainWindow.focus();

View File

@ -4,6 +4,9 @@ import PATHS from './../helpers/src-paths';
const webpackConfig = require('./../../webpack.config.js'); const webpackConfig = require('./../../webpack.config.js');
gulp.task('build-app', ['build-static'], () => gulp.src(PATHS.APP_MAIN_JS) gulp.task('build-app', ['build-static'], () =>
gulp
.src(PATHS.APP_MAIN_JS)
.pipe(webpack(webpackConfig)) .pipe(webpack(webpackConfig))
.pipe(gulp.dest(PATHS.APP_DEST))); .pipe(gulp.dest(PATHS.APP_DEST)),
);

View File

@ -4,4 +4,6 @@ import helpers from './../helpers/gulp-helpers';
const { buildES6 } = 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),
);

View File

@ -4,9 +4,14 @@ import helpers from './../helpers/gulp-helpers';
const { buildES6 } = helpers; const { buildES6 } = helpers;
gulp.task('build-static-not-js', () => gulp.src([PATHS.APP_STATIC_ALL, '!**/*.js']) gulp.task('build-static-not-js', () =>
.pipe(gulp.dest(PATHS.APP_STATIC_DEST))); 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']); gulp.task('build-static', ['build-static-js', 'build-static-not-js']);

View File

@ -14,7 +14,8 @@ function shellExec(cmd, silent, callback) {
} }
function buildES6(src, dest, callback) { function buildES6(src, dest, callback) {
return gulp.src(src) return gulp
.src(src)
.pipe(sourcemaps.init()) .pipe(sourcemaps.init())
.pipe(babel()) .pipe(babel())
.on('error', callback) .on('error', callback)

View File

@ -8,4 +8,4 @@ gulp.task('publish', (done) => {
shellExec('npm publish', false, done); shellExec('npm publish', false, done);
}); });
gulp.task('release', callback => runSequence('build', 'publish', callback)); gulp.task('release', (callback) => runSequence('build', 'publish', callback));

View File

@ -23,7 +23,8 @@
"watch": "while true ; do gulp watch ; done", "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", "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", "start-placeholder": "npm run build && electron app",
"changelog": "./scripts/changelog" "changelog": "./scripts/changelog",
"format": "prettier --write '{gulp,src}/**/*.js' 'app/src/**/*.js'"
}, },
"bin": { "bin": {
"nativefier": "lib/cli.js" "nativefier": "lib/cli.js"
@ -68,11 +69,14 @@
"del": "^3.0.0", "del": "^3.0.0",
"eslint": "^4.17.0", "eslint": "^4.17.0",
"eslint-config-airbnb-base": "^12.1.0", "eslint-config-airbnb-base": "^12.1.0",
"eslint-config-prettier": "^2.9.0",
"eslint-plugin-import": "^2.8.0", "eslint-plugin-import": "^2.8.0",
"eslint-plugin-prettier": "^2.6.0",
"gulp": "^3.9.1", "gulp": "^3.9.1",
"gulp-babel": "^7.0.1", "gulp-babel": "^7.0.1",
"gulp-sourcemaps": "^2.6.4", "gulp-sourcemaps": "^2.6.4",
"jest": "^22.1.4", "jest": "^22.1.4",
"prettier": "^1.12.1",
"regenerator-runtime": "^0.11.1", "regenerator-runtime": "^0.11.1",
"require-dir": "^1.0.0", "require-dir": "^1.0.0",
"run-sequence": "^2.2.1", "run-sequence": "^2.2.1",

View File

@ -64,7 +64,9 @@ function maybeCopyScripts(srcs, dest) {
resolve(); resolve();
}); });
} }
const promises = srcs.map(src => new Promise((resolve, reject) => { const promises = srcs.map(
(src) =>
new Promise((resolve, reject) => {
if (!fs.existsSync(src)) { if (!fs.existsSync(src)) {
reject(new Error('Error copying injection files: file not found')); reject(new Error('Error copying injection files: file not found'));
return; return;
@ -87,7 +89,8 @@ function maybeCopyScripts(srcs, dest) {
} }
resolve(); resolve();
}); });
})); }),
);
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
Promise.all(promises) Promise.all(promises)
@ -133,7 +136,10 @@ function buildApp(src, dest, options, callback) {
return; 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) maybeCopyScripts(options.inject, dest)
.catch((err) => { .catch((err) => {
@ -146,5 +152,4 @@ function buildApp(src, dest, options, callback) {
}); });
} }
export default buildApp; export default buildApp;

View File

@ -28,7 +28,10 @@ function getAppPath(appPathArray) {
} }
if (appPathArray.length > 1) { 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]; return appPathArray[0];
@ -43,7 +46,9 @@ function maybeNoIconOption(options) {
const packageOptions = JSON.parse(JSON.stringify(options)); const packageOptions = JSON.parse(JSON.stringify(options));
if (options.platform === 'win32' && !isWindows()) { if (options.platform === 'win32' && !isWindows()) {
if (!hasBinary.sync('wine')) { 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; packageOptions.icon = null;
} }
} }
@ -86,7 +91,9 @@ function removeInvalidOptions(options, param) {
const packageOptions = JSON.parse(JSON.stringify(options)); const packageOptions = JSON.parse(JSON.stringify(options));
if (options.platform === 'win32' && !isWindows()) { if (options.platform === 'win32' && !isWindows()) {
if (!hasBinary.sync('wine')) { 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; packageOptions[param] = null;
} }
} }
@ -161,13 +168,15 @@ function buildMain(inpOptions, callback) {
const progress = new DishonestProgress(5); const progress = new DishonestProgress(5);
async.waterfall([ async.waterfall(
[
(cb) => { (cb) => {
progress.tick('inferring'); progress.tick('inferring');
optionsFactory(options) optionsFactory(options)
.then((result) => { .then((result) => {
cb(null, result); cb(null, result);
}).catch((error) => { })
.catch((error) => {
cb(error); cb(error);
}); });
}, },
@ -179,7 +188,9 @@ function buildMain(inpOptions, callback) {
return; return;
} }
// Change the reference file for the Electron app to be the temporary path // Change the reference file for the Electron app to be the temporary path
const newOptions = Object.assign({}, opts, { dir: tmpPath }); const newOptions = Object.assign({}, opts, {
dir: tmpPath,
});
cb(null, newOptions); cb(null, newOptions);
}); });
}, },
@ -225,10 +236,12 @@ function buildMain(inpOptions, callback) {
cb(error, appPath); cb(error, appPath);
}); });
}, },
], (error, appPath) => { ],
(error, appPath) => {
packagerConsole.playback(); packagerConsole.playback();
callback(error, appPath); callback(error, appPath);
}); },
);
} }
export default buildMain; export default buildMain;

View File

@ -84,7 +84,9 @@ function iconBuild(inpOptions, callback) {
} }
if (!isOSX()) { 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(); returnCallback();
return; return;
} }

View File

@ -28,12 +28,13 @@ function getProcessEnvs(val) {
function checkInternet() { function checkInternet() {
dns.lookup('npmjs.com', (err) => { dns.lookup('npmjs.com', (err) => {
if (err && err.code === 'ENOTFOUND') { 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) { if (require.main === module) {
program program
.version(packageJson.version) .version(packageJson.version)
@ -43,51 +44,153 @@ if (require.main === module) {
program.out = appDir; program.out = appDir;
}) })
.option('-n, --name <value>', 'app name') .option('-n, --name <value>', 'app name')
.option('-p, --platform <value>', '\'osx\', \'mas\', \'linux\' or \'windows\'') .option('-p, --platform <value>', "'osx', 'mas', 'linux' or 'windows'")
.option('-a, --arch <value>', '\'ia32\' or \'x64\' or \'armv7l\'') .option('-a, --arch <value>', "'ia32' or 'x64' or 'armv7l'")
.option('--app-version <value>', 'The release version of the application. Maps to the `ProductVersion` metadata property on Windows, and `CFBundleShortVersionString` on OS X.') .option(
.option('--build-version <value>', 'The build version of the application. Maps to the `FileVersion` metadata property on Windows, and `CFBundleVersion` on OS X.') '--app-version <value>',
.option('--app-copyright <value>', 'The human-readable copyright line for the app. Maps to the `LegalCopyright` metadata property on Windows, and `NSHumanReadableCopyright` on OS X') 'The release version of the application. Maps to the `ProductVersion` metadata property on Windows, and `CFBundleShortVersionString` on OS X.',
.option('--win32metadata <json-string>', '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 <value>', 'electron version to package, without the \'v\', see https://github.com/atom/electron/releases') .option(
.option('--no-overwrite', 'do not override output directory if it already exists, defaults to false') '--build-version <value>',
.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/') 'The build version of the application. Maps to the `FileVersion` metadata property on Windows, and `CFBundleVersion` on OS X.',
.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(
.option('-i, --icon <value>', 'the icon file to use as the icon for the app (should be a .png)') '--app-copyright <value>',
.option('--width <value>', 'set window default width, defaults to 1280px', parseInt) 'The human-readable copyright line for the app. Maps to the `LegalCopyright` metadata property on Windows, and `NSHumanReadableCopyright` on OS X',
.option('--height <value>', 'set window default height, defaults to 800px', parseInt) )
.option('--min-width <value>', 'set window minimum width, defaults to 0px', parseInt) .option(
.option('--min-height <value>', 'set window minimum height, defaults to 0px', parseInt) '--win32metadata <json-string>',
.option('--max-width <value>', 'set window maximum width, default is no limit', parseInt) 'a JSON string of key/value pairs of application metadata (ProductName, InternalName, FileDescription) to embed into the executable (Windows only).',
.option('--max-height <value>', 'set window maximum height, default is no limit', parseInt) parseJson,
)
.option(
'-e, --electron-version <value>',
"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 <value>',
'the icon file to use as the icon for the app (should be a .png)',
)
.option(
'--width <value>',
'set window default width, defaults to 1280px',
parseInt,
)
.option(
'--height <value>',
'set window default height, defaults to 800px',
parseInt,
)
.option(
'--min-width <value>',
'set window minimum width, defaults to 0px',
parseInt,
)
.option(
'--min-height <value>',
'set window minimum height, defaults to 0px',
parseInt,
)
.option(
'--max-width <value>',
'set window maximum width, default is no limit',
parseInt,
)
.option(
'--max-height <value>',
'set window maximum height, default is no limit',
parseInt,
)
.option('--x <value>', 'set window x location', parseInt) .option('--x <value>', 'set window x location', parseInt)
.option('--y <value>', 'set window y location', parseInt) .option('--y <value>', 'set window y location', parseInt)
.option('-m, --show-menu-bar', 'set menu bar visible, defaults to false') .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 <value>', 'set the user agent string for the app') .option('-u, --user-agent <value>', '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('--ignore-certificate', 'ignore certificate related errors')
.option('--disable-gpu', 'disable hardware acceleration') .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('--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', 'if flash should be enabled')
.option('--flash-path <value>', 'path to Chrome flash plugin, find it in `Chrome://plugins`') .option(
.option('--disk-cache-size <value>', 'forces the maximum disk space (in bytes) to be used by the disk cache') '--flash-path <value>',
.option('--inject <value>', 'path to a CSS/JS file to be injected', collect, []) 'path to Chrome flash plugin, find it in `Chrome://plugins`',
.option('--full-screen', 'if the app should always be started in full screen') )
.option(
'--disk-cache-size <value>',
'forces the maximum disk space (in bytes) to be used by the disk cache',
)
.option(
'--inject <value>',
'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('--maximize', 'if the app should always be started maximized')
.option('--hide-window-frame', 'disable window frame and controls') .option('--hide-window-frame', 'disable window frame and controls')
.option('--verbose', 'if verbose logs should be displayed') .option('--verbose', 'if verbose logs should be displayed')
.option('--disable-context-menu', 'disable the context menu') .option('--disable-context-menu', 'disable the context menu')
.option('--disable-dev-tools', 'disable developer tools') .option('--disable-dev-tools', 'disable developer tools')
.option('--zoom <value>', 'default zoom factor to use when the app is opened, defaults to 1.0', parseFloat) .option(
.option('--internal-urls <value>', '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)') '--zoom <value>',
.option('--crash-reporter <value>', 'remote server URL to send crash reports') 'default zoom factor to use when the app is opened, defaults to 1.0',
.option('--single-instance', 'allow only a single instance of the application') parseFloat,
.option('--processEnvs <json-string>', 'a JSON string of key/value pairs to be set as environment variables before any browser windows are opened.', getProcessEnvs) )
.option('--file-download-options <json-string>', '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(
'--internal-urls <value>',
'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 <value>',
'remote server URL to send crash reports',
)
.option(
'--single-instance',
'allow only a single instance of the application',
)
.option(
'--processEnvs <json-string>',
'a JSON string of key/value pairs to be set as environment variables before any browser windows are opened.',
getProcessEnvs,
)
.option(
'--file-download-options <json-string>',
'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('--tray', 'allow app to stay in system tray')
.option('--basic-auth-username <value>', 'basic http(s) auth username') .option('--basic-auth-username <value>', 'basic http(s) auth username')
.option('--basic-auth-password <value>', 'basic http(s) auth password') .option('--basic-auth-password <value>', 'basic http(s) auth password')

View File

@ -26,13 +26,19 @@ function convertToIcns(pngSrc, icnsDest, callback) {
return; return;
} }
shell.exec(`${PNG_TO_ICNS_BIN_PATH} ${pngSrc} ${icnsDest}`, { silent: true }, (exitCode, stdOut, stdError) => { shell.exec(
`${PNG_TO_ICNS_BIN_PATH} ${pngSrc} ${icnsDest}`,
{ silent: true },
(exitCode, stdOut, stdError) => {
if (stdOut.includes('icon.iconset:error') || exitCode) { if (stdOut.includes('icon.iconset:error') || exitCode) {
if (exitCode) { if (exitCode) {
callback({ callback(
{
stdOut, stdOut,
stdError, stdError,
}, pngSrc); },
pngSrc,
);
return; return;
} }
@ -41,7 +47,8 @@ function convertToIcns(pngSrc, icnsDest, callback) {
} }
callback(null, icnsDest); callback(null, icnsDest);
}); },
);
} }
/** /**

View File

@ -12,7 +12,8 @@ function isWindows() {
} }
function downloadFile(fileUrl) { function downloadFile(fileUrl) {
return axios.get(fileUrl, { return axios
.get(fileUrl, {
responseType: 'arraybuffer', responseType: 'arraybuffer',
}) })
.then((response) => { .then((response) => {
@ -55,7 +56,9 @@ function allowedIconFormats(platform) {
formats.push('.ico'); formats.push('.ico');
break; break;
default: default:
throw new Error(`function allowedIconFormats error: Unknown platform ${platform}`); throw new Error(
`function allowedIconFormats error: Unknown platform ${platform}`,
);
} }
return formats; return formats;
} }
@ -89,7 +92,9 @@ function allowedIconFormats(platform) {
} }
break; break;
default: default:
throw new Error(`function allowedIconFormats error: Unknown platform ${platform}`); throw new Error(
`function allowedIconFormats error: Unknown platform ${platform}`,
);
} }
return formats; return formats;
} }

View File

@ -27,7 +27,10 @@ function iconShellHelper(shellScriptPath, icoSrc, dest) {
return; return;
} }
shell.exec(`${shellScriptPath} ${icoSrc} ${dest}`, { silent: true }, (exitCode, stdOut, stdError) => { shell.exec(
`${shellScriptPath} ${icoSrc} ${dest}`,
{ silent: true },
(exitCode, stdOut, stdError) => {
if (exitCode) { if (exitCode) {
// eslint-disable-next-line prefer-promise-reject-errors // eslint-disable-next-line prefer-promise-reject-errors
reject({ reject({
@ -38,7 +41,8 @@ function iconShellHelper(shellScriptPath, icoSrc, dest) {
} }
resolve(dest); resolve(dest);
}); },
);
}); });
} }
@ -54,22 +58,40 @@ function getTmpDirPath() {
*/ */
function singleIco(icoSrc) { function singleIco(icoSrc) {
return iconShellHelper(SCRIPT_PATHS.singleIco, icoSrc, `${getTmpDirPath()}/icon.ico`); return iconShellHelper(
SCRIPT_PATHS.singleIco,
icoSrc,
`${getTmpDirPath()}/icon.ico`,
);
} }
function convertToPng(icoSrc) { function convertToPng(icoSrc) {
return iconShellHelper(SCRIPT_PATHS.convertToPng, icoSrc, `${getTmpDirPath()}/icon.png`); return iconShellHelper(
SCRIPT_PATHS.convertToPng,
icoSrc,
`${getTmpDirPath()}/icon.png`,
);
} }
function convertToIco(icoSrc) { function convertToIco(icoSrc) {
return iconShellHelper(SCRIPT_PATHS.convertToIco, icoSrc, `${getTmpDirPath()}/icon.ico`); return iconShellHelper(
SCRIPT_PATHS.convertToIco,
icoSrc,
`${getTmpDirPath()}/icon.ico`,
);
} }
function convertToIcns(icoSrc) { function convertToIcns(icoSrc) {
if (!isOSX()) { 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 { export default {

View File

@ -25,14 +25,13 @@ function getMaxMatchScore(iconWithScores) {
*/ */
function getMatchingIcons(iconsWithScores, maxScore) { function getMatchingIcons(iconsWithScores, maxScore) {
return iconsWithScores return iconsWithScores
.filter(item => item.score === maxScore) .filter((item) => item.score === maxScore)
.map(item => Object.assign({}, item, { ext: path.extname(item.url) })); .map((item) => Object.assign({}, item, { ext: path.extname(item.url) }));
} }
function mapIconWithMatchScore(fileIndex, targetUrl) { function mapIconWithMatchScore(fileIndex, targetUrl) {
const normalisedTargetUrl = targetUrl.toLowerCase(); const normalisedTargetUrl = targetUrl.toLowerCase();
return fileIndex return fileIndex.map((item) => {
.map((item) => {
const itemWords = item.name.split(GITCLOUD_SPACE_DELIMITER); const itemWords = item.name.split(GITCLOUD_SPACE_DELIMITER);
const score = itemWords.reduce((currentScore, word) => { const score = itemWords.reduce((currentScore, word) => {
if (normalisedTargetUrl.includes(word)) { if (normalisedTargetUrl.includes(word)) {
@ -48,8 +47,8 @@ function mapIconWithMatchScore(fileIndex, targetUrl) {
function inferIconFromStore(targetUrl, platform) { function inferIconFromStore(targetUrl, platform) {
const allowedFormats = new Set(allowedIconFormats(platform)); const allowedFormats = new Set(allowedIconFormats(platform));
return gitCloud('https://jiahaog.github.io/nativefier-icons/') return gitCloud('https://jiahaog.github.io/nativefier-icons/').then(
.then((fileIndex) => { (fileIndex) => {
const iconWithScores = mapIconWithMatchScore(fileIndex, targetUrl); const iconWithScores = mapIconWithMatchScore(fileIndex, targetUrl);
const maxScore = getMaxMatchScore(iconWithScores); const maxScore = getMaxMatchScore(iconWithScores);
@ -58,7 +57,9 @@ function inferIconFromStore(targetUrl, platform) {
} }
const iconsMatchingScore = getMatchingIcons(iconWithScores, maxScore); 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 matchingIcon = iconsMatchingExt[0];
const iconUrl = matchingIcon && matchingIcon.url; const iconUrl = matchingIcon && matchingIcon.url;
@ -66,7 +67,8 @@ function inferIconFromStore(targetUrl, platform) {
return null; return null;
} }
return downloadFile(iconUrl); return downloadFile(iconUrl);
}); },
);
} }
function writeFilePromise(outPath, data) { function writeFilePromise(outPath, data) {
@ -88,8 +90,7 @@ function inferFromPage(targetUrl, platform, outDir) {
} }
// todo might want to pass list of preferences instead // todo might want to pass list of preferences instead
return pageIcon(targetUrl, { ext: preferredExt }) return pageIcon(targetUrl, { ext: preferredExt }).then((icon) => {
.then((icon) => {
if (!icon) { if (!icon) {
return null; return null;
} }
@ -106,8 +107,7 @@ function inferFromPage(targetUrl, platform, outDir) {
* @param {string} outDir * @param {string} outDir
*/ */
function inferIconFromUrlToPath(targetUrl, platform, outDir) { function inferIconFromUrlToPath(targetUrl, platform, outDir) {
return inferIconFromStore(targetUrl, platform) return inferIconFromStore(targetUrl, platform).then((icon) => {
.then((icon) => {
if (!icon) { if (!icon) {
return inferFromPage(targetUrl, platform, outDir); return inferFromPage(targetUrl, platform, outDir);
} }

View File

@ -2,7 +2,12 @@ import os from 'os';
function inferPlatform() { function inferPlatform() {
const platform = os.platform(); const platform = os.platform();
if ((platform === 'darwin' || platform === 'mas') || platform === 'win32' || platform === 'linux') { if (
platform === 'darwin' ||
platform === 'mas' ||
platform === 'win32' ||
platform === 'linux'
) {
return platform; return platform;
} }

View File

@ -1,7 +1,8 @@
import axios from 'axios'; import axios from 'axios';
import cheerio from 'cheerio'; 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) { function inferTitle(url) {
const options = { const options = {
@ -15,7 +16,10 @@ function inferTitle(url) {
return axios(options).then(({ data }) => { return axios(options).then(({ data }) => {
const $ = cheerio.load(data); const $ = cheerio.load(data);
return $('title').first().text().replace(/\//g, ''); return $('title')
.first()
.text()
.replace(/\//g, '');
}); });
} }

View File

@ -5,21 +5,25 @@ import log from 'loglevel';
const ELECTRON_VERSIONS_URL = 'https://atom.io/download/atom-shell/index.json'; const ELECTRON_VERSIONS_URL = 'https://atom.io/download/atom-shell/index.json';
const DEFAULT_CHROME_VERSION = '58.0.3029.110'; const DEFAULT_CHROME_VERSION = '58.0.3029.110';
function getChromeVersionForElectronVersion(electronVersion, url = ELECTRON_VERSIONS_URL) { function getChromeVersionForElectronVersion(
return axios.get(url, { timeout: 5000 }) electronVersion,
.then((response) => { url = ELECTRON_VERSIONS_URL,
) {
return axios.get(url, { timeout: 5000 }).then((response) => {
if (response.status !== 200) { if (response.status !== 200) {
throw new Error(`Bad request: Status code ${response.status}`); throw new Error(`Bad request: Status code ${response.status}`);
} }
const { data } = response; const { data } = response;
const electronVersionToChromeVersion = _.zipObject( const electronVersionToChromeVersion = _.zipObject(
data.map(d => d.version), data.map((d) => d.version),
data.map(d => d.chrome), data.map((d) => d.chrome),
); );
if (!(electronVersion in electronVersionToChromeVersion)) { if (!(electronVersion in electronVersionToChromeVersion)) {
throw new Error(`Electron version '${electronVersion}' not found in retrieved version list!`); throw new Error(
`Electron version '${electronVersion}' not found in retrieved version list!`,
);
} }
return electronVersionToChromeVersion[electronVersion]; return electronVersionToChromeVersion[electronVersion];
@ -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`; userAgent = `Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/${chromeVersion} Safari/537.36`;
break; break;
default: default:
throw new Error('Error invalid platform specified to getUserAgentString()'); throw new Error(
'Error invalid platform specified to getUserAgentString()',
);
} }
return userAgent; return userAgent;
} }
function inferUserAgent(electronVersion, platform, url = ELECTRON_VERSIONS_URL) { function inferUserAgent(
electronVersion,
platform,
url = ELECTRON_VERSIONS_URL,
) {
return getChromeVersionForElectronVersion(electronVersion, url) return getChromeVersionForElectronVersion(electronVersion, url)
.then(chromeVersion => getUserAgentString(chromeVersion, platform)) .then((chromeVersion) => getUserAgentString(chromeVersion, platform))
.catch(() => { .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); return getUserAgentString(DEFAULT_CHROME_VERSION, platform);
}); });
} }

View File

@ -20,7 +20,9 @@ function testPlatform(platform) {
describe('Infer User Agent', () => { describe('Infer User Agent', () => {
test('Can infer userAgent for all platforms', (done) => { 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) Promise.all(testPromises)
.then(() => { .then(() => {
done(); done();
@ -36,7 +38,9 @@ describe('Infer User Agent', () => {
const TIMEOUT_URL = 'http://www.google.com:81/'; const TIMEOUT_URL = 'http://www.google.com:81/';
inferUserAgent('1.6.7', 'darwin', TIMEOUT_URL) inferUserAgent('1.6.7', 'darwin', TIMEOUT_URL)
.then((userAgent) => { .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(); done();
}) })
.catch(done); .catch(done);

View File

@ -1,7 +1,10 @@
import fields from './fields'; import fields from './fields';
function resultArrayToObject(fieldResults) { 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) { function inferredOptions(oldOptions, fieldResults) {
@ -11,8 +14,9 @@ function inferredOptions(oldOptions, fieldResults) {
// Takes the options object and infers new values // Takes the options object and infers new values
// which may need async work // which may need async work
export default function (options) { export default function(options) {
const tasks = fields(options); const tasks = fields(options);
return Promise.all(tasks) return Promise.all(tasks).then((fieldResults) =>
.then(fieldResults => inferredOptions(options, fieldResults)); inferredOptions(options, fieldResults),
);
} }

View File

@ -3,9 +3,11 @@ import fields from './fields';
jest.mock('./fields'); jest.mock('./fields');
fields.mockImplementation(() => [Promise.resolve({ fields.mockImplementation(() => [
Promise.resolve({
someField: 'newValue', someField: 'newValue',
})]); }),
]);
test('it should merge the result of the promise', () => { test('it should merge the result of the promise', () => {
const param = { another: 'field', someField: 'oldValue' }; const param = { another: 'field', someField: 'oldValue' };
@ -15,4 +17,3 @@ test('it should merge the result of the promise', () => {
expect(result).toEqual(expected); expect(result).toEqual(expected);
}); });
}); });

View File

@ -1,14 +1,13 @@
import log from 'loglevel'; import log from 'loglevel';
import { inferIcon } from './../../infer'; import { inferIcon } from './../../infer';
export default function ({ icon, targetUrl, platform }) { export default function({ icon, targetUrl, platform }) {
// Icon is the path to the icon // Icon is the path to the icon
if (icon) { if (icon) {
return Promise.resolve(icon); return Promise.resolve(icon);
} }
return inferIcon(targetUrl, platform) return inferIcon(targetUrl, platform).catch((error) => {
.catch((error) => {
log.warn('Cannot automatically retrieve the app icon:', error); log.warn('Cannot automatically retrieve the app icon:', error);
return null; return null;
}); });

View File

@ -29,12 +29,17 @@ describe('when the icon parameter is not passed', () => {
describe('when inferIcon resolves with an error', () => { describe('when inferIcon resolves with an error', () => {
test('it should handle the 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' }; const params = { targetUrl: 'some url', platform: 'mac' };
return icon(params).then((result) => { return icon(params).then((result) => {
expect(result).toBe(null); expect(result).toBe(null);
expect(inferIcon).toHaveBeenCalledWith(params.targetUrl, params.platform); expect(inferIcon).toHaveBeenCalledWith(
params.targetUrl,
params.platform,
);
expect(log.warn).toHaveBeenCalledTimes(1); expect(log.warn).toHaveBeenCalledTimes(1);
}); });
}); });

View File

@ -2,28 +2,31 @@ import icon from './icon';
import userAgent from './userAgent'; import userAgent from './userAgent';
import name from './name'; import name from './name';
const fields = [{ const fields = [
{
field: 'userAgent', field: 'userAgent',
task: userAgent, task: userAgent,
}, { },
{
field: 'icon', field: 'icon',
task: icon, task: icon,
}, { },
{
field: 'name', field: 'name',
task: name, task: name,
}]; },
];
// Modifies the result of each promise from a scalar // Modifies the result of each promise from a scalar
// value to a object containing its fieldname // value to a object containing its fieldname
function wrap(fieldName, promise, args) { function wrap(fieldName, promise, args) {
return promise(args) return promise(args).then((result) => ({
.then(result => ({
[fieldName]: result, [fieldName]: result,
})); }));
} }
// Returns a list of promises which will all resolve // Returns a list of promises which will all resolve
// with the following result: {[fieldName]: fieldvalue} // with the following result: {[fieldName]: fieldvalue}
export default function (options) { export default function(options) {
return fields.map(({ field, task }) => wrap(field, task, options)); return fields.map(({ field, task }) => wrap(field, task, options));
} }

View File

@ -19,4 +19,3 @@ test('it should return a list of promises', () => {
expect(value).toBeInstanceOf(Promise); expect(value).toBeInstanceOf(Promise);
}); });
}); });

View File

@ -10,14 +10,17 @@ function tryToInferName({ name, targetUrl }) {
} }
return inferTitle(targetUrl) return inferTitle(targetUrl)
.then(pageTitle => (pageTitle || DEFAULT_APP_NAME)) .then((pageTitle) => pageTitle || DEFAULT_APP_NAME)
.catch((error) => { .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; return DEFAULT_APP_NAME;
}); });
} }
export default function ({ platform, name, targetUrl }) { export default function({ platform, name, targetUrl }) {
return tryToInferName({ name, targetUrl }) return tryToInferName({ name, targetUrl }).then((result) =>
.then(result => sanitizeFilename(platform, result)); sanitizeFilename(platform, result),
);
} }

View File

@ -14,12 +14,14 @@ const mockedResult = 'mock name';
describe('well formed name parameters', () => { describe('well formed name parameters', () => {
const params = { name: 'appname', platform: 'something' }; const params = { name: 'appname', platform: 'something' };
test('it should not call inferTitle', () => name(params).then((result) => { test('it should not call inferTitle', () =>
name(params).then((result) => {
expect(inferTitle).toHaveBeenCalledTimes(0); expect(inferTitle).toHaveBeenCalledTimes(0);
expect(result).toBe(params.name); expect(result).toBe(params.name);
})); }));
test('it should call sanitize filename', () => name(params).then((result) => { test('it should call sanitize filename', () =>
name(params).then((result) => {
expect(sanitizeFilename).toHaveBeenCalledWith(params.platform, result); expect(sanitizeFilename).toHaveBeenCalledWith(params.platform, result);
})); }));
}); });
@ -31,7 +33,8 @@ describe('bad name parameters', () => {
const params = { targetUrl: 'some url' }; const params = { targetUrl: 'some url' };
describe('when the name is undefined', () => { describe('when the name is undefined', () => {
test('it should call inferTitle', () => name(params).then(() => { test('it should call inferTitle', () =>
name(params).then(() => {
expect(inferTitle).toHaveBeenCalledWith(params.targetUrl); expect(inferTitle).toHaveBeenCalledWith(params.targetUrl);
})); }));
}); });
@ -46,7 +49,8 @@ describe('bad name parameters', () => {
}); });
}); });
test('it should call sanitize filename', () => name(params).then((result) => { test('it should call sanitize filename', () =>
name(params).then((result) => {
expect(sanitizeFilename).toHaveBeenCalledWith(params.platform, result); expect(sanitizeFilename).toHaveBeenCalledWith(params.platform, result);
})); }));
}); });
@ -75,7 +79,9 @@ describe('handling inferTitle results', () => {
describe('when inferTitle resolves with an error', () => { describe('when inferTitle resolves with an error', () => {
test('it should return the default app name', () => { 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) => { return name(params).then((result) => {
expect(result).toBe(DEFAULT_APP_NAME); expect(result).toBe(DEFAULT_APP_NAME);

View File

@ -1,6 +1,6 @@
import { inferUserAgent } from './../../infer'; import { inferUserAgent } from './../../infer';
export default function ({ userAgent, electronVersion, platform }) { export default function({ userAgent, electronVersion, platform }) {
if (userAgent) { if (userAgent) {
return Promise.resolve(userAgent); return Promise.resolve(userAgent);
} }

View File

@ -13,6 +13,8 @@ test('when a userAgent parameter is passed', () => {
test('no userAgent parameter is passed', () => { test('no userAgent parameter is passed', () => {
const params = { electronVersion: '123', platform: 'mac' }; const params = { electronVersion: '123', platform: 'mac' };
userAgent(params); userAgent(params);
expect(inferUserAgent).toHaveBeenCalledWith(params.electronVersion, params.platform); expect(inferUserAgent).toHaveBeenCalledWith(
params.electronVersion,
params.platform,
);
}); });

View File

@ -1,7 +1,9 @@
import normalizeUrl from './normalizeUrl'; import normalizeUrl from './normalizeUrl';
test("a proper URL shouldn't be mangled", () => { 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', () => { 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", () => { 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!');
}); });

View File

@ -13,7 +13,7 @@ const { inferPlatform, inferArch } = inferOs;
* @param {Object} inpOptions * @param {Object} inpOptions
* @returns {Promise} * @returns {Promise}
*/ */
export default function (inpOptions) { export default function(inpOptions) {
const options = { const options = {
dir: PLACEHOLDER_APP_DIR, dir: PLACEHOLDER_APP_DIR,
name: inpOptions.name, name: inpOptions.name,
@ -93,7 +93,10 @@ export default function (inpOptions) {
options.platform = 'win32'; options.platform = 'win32';
} }
if (options.platform.toLowerCase() === 'osx' || options.platform.toLowerCase() === 'mac') { if (
options.platform.toLowerCase() === 'osx' ||
options.platform.toLowerCase() === 'mac'
) {
options.platform = 'darwin'; options.platform = 'darwin';
} }

View File

@ -2,7 +2,7 @@ import _ from 'lodash';
import sanitizeFilenameLib from 'sanitize-filename'; import sanitizeFilenameLib from 'sanitize-filename';
import { DEFAULT_APP_NAME } from './../constants'; import { DEFAULT_APP_NAME } from './../constants';
export default function (platform, str) { export default function(platform, str) {
let result = sanitizeFilenameLib(str); let result = sanitizeFilenameLib(str);
// remove all non ascii or use default app name // remove all non ascii or use default app name

View File

@ -3,7 +3,7 @@ import sanitizeFilename from './sanitizeFilename';
import { DEFAULT_APP_NAME } from './../constants'; import { DEFAULT_APP_NAME } from './../constants';
jest.mock('sanitize-filename'); jest.mock('sanitize-filename');
sanitizeFilenameLib.mockImplementation(str => str); sanitizeFilenameLib.mockImplementation((str) => str);
test('it should call the sanitize-filename npm module', () => { test('it should call the sanitize-filename npm module', () => {
const param = 'abc'; const param = 'abc';