Cleanup options.js, rename `--app-name` to `--name`

This commit is contained in:
Jia Hao 2016-01-29 11:37:54 +08:00
parent 0d408b001d
commit 51acbaaa9c
10 changed files with 112 additions and 133 deletions

View File

@ -1,6 +1,7 @@
# Nativefier
[![Build Status](https://travis-ci.org/jiahaog/nativefier.svg?branch=master)](https://travis-ci.org/jiahaog/nativefier)
[![npm version](https://badge.fury.io/js/nativefier.svg)](https://www.npmjs.com/package/nativefier)
![Dock Screenshot](https://raw.githubusercontent.com/jiahaog/nativefier/master/screenshots/Dock%20Screenshot.png)
You want to make a native wrapper for Google Maps (or any web page).
@ -19,6 +20,10 @@ I did this because I was tired of having to `⌘-tab` or `alt-tab` to my browser
View the changelog [here](https://github.com/jiahaog/nativefier/blob/master/History.md).
### Features
- Automatically retrieves the correct icon and app name
## Installation
With [Node.js](https://nodejs.org/) installed,
@ -54,10 +59,10 @@ Creating a native desktop app for [medium.com](http://medium.com):
$ nativefier "http://medium.com"
```
Nativefier will intelligently attempt to determine the app name, your OS and processor architecture, among other options. If desired, the app name or other options can be overwritten by specifying the `--app-name "Medium"` as part of the command line options, as such.
Nativefier will intelligently attempt to determine the app name, your OS and processor architecture, among other options. If desired, the app name or other options can be overwritten by specifying the `--name "Medium"` as part of the command line options, as such.
```
$ nativefier --app-name "Some Awesome App" "http://medium.com"
$ nativefier --name "Some Awesome App" "http://medium.com"
```
**For Windows Users:** Take note that the application menu is automatically hidden by default, you can press `alt` on your keyboard to access it.
@ -85,10 +90,10 @@ Specifies the destination directory to build the app to, defaults to the current
Prints the usage information.
#### [app-name]
#### [name]
```
-n, --app-name <value>
-n, --name <value>
```
The name of the application, which will affect strings in titles and the icon.

View File

@ -18,7 +18,7 @@
"clean": "gulp clean",
"build": "gulp build",
"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 --app-name notification-test --icon ./test-resources/iconSampleGrey.png && 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 && open ~/Desktop/notification-test-darwin-x64/notification-test.app",
"start-placeholder": "npm run build && electron app",
"release": "gulp release"
},

View File

@ -36,24 +36,7 @@ function buildApp(options, callback) {
async.waterfall([
callback => {
optionsFactory(
options.appName,
options.targetUrl,
options.platform,
options.arch,
options.electronVersion,
options.outDir,
options.overwrite,
options.conceal,
options.icon,
options.counter,
options.width,
options.height,
options.showMenuBar,
options.userAgent,
options.honest,
options.insecure,
callback);
optionsFactory(options, callback);
},
(options, callback) => {
copyPlaceholderApp(options.dir, tmpPath, options.name, options.targetUrl, options.counter, options.width, options.height, options.showMenuBar, options.userAgent, options.insecure, (error, tempDirPath) => {
@ -70,7 +53,6 @@ function buildApp(options, callback) {
// maybe skip passing icon parameter to electron packager
const packageOptions = maybeNoIconOption(options);
packager(packageOptions, (error, appPathArray) => {
// pass options which still contains the icon to waterfall
callback(error, options, appPathArray);

View File

@ -13,9 +13,9 @@ if (require.main === module) {
.arguments('<targetUrl> [dest]')
.action(function(targetUrl, appDir) {
program.targetUrl = targetUrl;
program.outDir = appDir;
program.out = appDir;
})
.option('-n, --app-name <value>', 'app name')
.option('-n, --name <value>', 'app name')
.option('-p, --platform <value>', '\'linux\', \'win32\', or \'darwin\'')
.option('-a, --arch <value>', '\'ia32\' or \'x64\'')
.option('-e, --electron-version <value>', 'electron version to package, without the \'v\', see https://github.com/atom/electron/releases')

View File

@ -7,6 +7,7 @@ function isOSX() {
function isWindows() {
return os.platform() === 'windows';
}
export default {
isOSX: isOSX,
isWindows: isWindows

24
src/infer/inferOs.js Normal file
View File

@ -0,0 +1,24 @@
import os from 'os';
function inferPlatform() {
const platform = os.platform();
if (platform === 'darwin' || platform === 'win32' || platform === 'linux') {
return platform;
}
console.warn(`Warning: Untested platform ${platform} detected, assuming linux`);
return 'linux';
}
function inferArch() {
const arch = os.arch();
if (arch !== 'ia32' && arch !== 'x64') {
throw `Incompatible architecture ${arch} detected`;
}
return arch;
}
export default {
inferPlatform: inferPlatform,
inferArch: inferArch
};

25
src/infer/inferTitle.js Normal file
View File

@ -0,0 +1,25 @@
import request from 'request';
import cheerio from 'cheerio';
function inferTitle(url, callback) {
const options = {
url: url,
headers: {
// fake a user agent because pages like http://messenger.com will throw 404 error
'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'
}
};
request(options, (error, response, body) => {
if (error || response.statusCode !== 200) {
callback(`Request Error: ${error}, Status Code ${response ? response.statusCode : 'No Response'}`);
return;
}
const $ = cheerio.load(body);
const pageTitle = $('title').text().replace(/\//g, '');
callback(null, pageTitle);
});
}
export default inferTitle;

View File

@ -1,80 +1,61 @@
import os from 'os';
import path from 'path';
import url from 'url';
import request from 'request';
import cheerio from 'cheerio';
import validator from 'validator';
import sanitize from 'sanitize-filename';
import sanitizeFilename from 'sanitize-filename';
import _ from 'lodash';
import async from 'async';
import inferIcon from './inferIcon';
import inferIcon from './infer/inferIcon';
import inferTitle from './infer/inferTitle';
import inferOs from './infer/inferOs';
const {inferPlatform, inferArch} = inferOs;
const TEMPLATE_APP_DIR = path.join(__dirname, '../', 'app');
const ELECTRON_VERSION = '0.36.4';
const DEFAULT_APP_NAME = 'APP';
function optionsFactory(name,
targetUrl,
platform = detectPlatform(),
arch = detectArch(),
version = ELECTRON_VERSION,
outDir = process.cwd(),
overwrite = false,
conceal = false,
icon,
counter = false,
width = 1280,
height = 800,
showMenuBar = false,
userAgent,
honest = false,
insecure = false,
callback) {
targetUrl = normalizeUrl(targetUrl);
/**
* @callback optionsCallback
* @param error
* @param options augmented options
*/
if (!width) {
width = 1280;
}
if (!height) {
height = 800;
}
if (!userAgent && !honest) {
userAgent = getFakeUserAgent();
}
/**
* Extracts only desired keys from inpOptions and augments it with defaults
* @param inpOptions
* @param {optionsCallback} callback
*/
function optionsFactory(inpOptions, callback) {
const options = {
dir: TEMPLATE_APP_DIR,
name: name,
targetUrl: targetUrl,
platform: platform,
arch: arch,
version: version,
out: outDir,
// optionals
overwrite: overwrite,
asar: conceal,
icon: icon,
// app configuration
counter: counter,
width: width,
height: height,
showMenuBar: showMenuBar,
userAgent: userAgent,
insecure: insecure
name: inpOptions.name,
targetUrl: normalizeUrl(inpOptions.targetUrl),
platform: inpOptions.platform || inferPlatform(),
arch: inpOptions.arch || inferArch(),
version: ELECTRON_VERSION,
out: inpOptions.out|| process.cwd(),
overwrite: inpOptions.overwrite || false,
asar: inpOptions.conceal || false,
icon: inpOptions.icon,
counter: inpOptions.counter || false,
width: inpOptions.width || 1280,
height: inpOptions.height || 800,
showMenuBar: inpOptions.showMenuBar || false,
userAgent: inpOptions.userAgent || getFakeUserAgent(),
insecure: inpOptions.insecure || false
};
if (inpOptions.honest) {
options.userAgent = null;
}
async.waterfall([
callback => {
if (options.icon) {
callback(null, options);
callback();
return;
}
inferIcon(options.targetUrl, (error, pngPath) => {
@ -83,80 +64,41 @@ function optionsFactory(name,
} else {
options.icon = pngPath;
}
callback(null, options);
callback();
});
},
(options, callback) => {
if (name && name.length > 0) {
options.name = name;
callback(null, options);
callback => {
if (options.name && options.name.length > 0) {
callback();
return;
}
getTitle(options.targetUrl, function(error, pageTitle) {
inferTitle(options.targetUrl, function(error, pageTitle) {
if (error) {
console.warn(`Unable to automatically determine app name, falling back to '${DEFAULT_APP_NAME}'`);
options.name = DEFAULT_APP_NAME;
} else {
options.name = pageTitle;
}
callback(null, options);
callback();
});
}
], (error, options) => {
], error => {
callback(error, sanitizeOptions(options));
console.log(options);
});
}
function sanitizeOptions(options) {
options.name = sanitize(options.name);
options.name = sanitizeFilename(options.name);
if (options.platform === 'linux') {
// spaces will cause problems with Ubuntu when pinned to the dock
options.name = _.kebabCase(options.name);
}
return options;
}
function detectPlatform() {
const platform = os.platform();
if (platform === 'darwin' || platform === 'win32' || platform === 'linux') {
return platform;
}
console.warn(`Warning: Untested platform ${platform} detected, assuming linux`);
return 'linux';
}
function detectArch() {
const arch = os.arch();
if (arch !== 'ia32' && arch !== 'x64') {
throw `Incompatible architecture ${arch} detected`;
}
return os.arch();
}
function getTitle(url, callback) {
const options = {
url: url,
headers: {
// fake a user agent because pages like http://messenger.com will throw 404 error
'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'
}
};
request(options, (error, response, body) => {
if (error || response.statusCode !== 200) {
callback(`Request Error: ${error}, Status Code ${response ? response.statusCode : 'No Response'}`);
return;
}
const $ = cheerio.load(body);
const pageTitle = $('title').text().replace(/\//g, '');
callback(null, pageTitle);
});
}
function normalizeUrl(testUrl) {
// add protocol if protocol not found
let normalized = testUrl;

View File

@ -49,7 +49,7 @@ describe('Nativefier Module', function() {
const tmpPath = tmpObj.name;
const options = {
appName: 'google-test-app',
name: 'google-test-app',
targetUrl: 'http://google.com',
outDir: tmpPath,
overwrite: true,