Skip to content
This repository has been archived by the owner on Jan 24, 2025. It is now read-only.

feat(docz-core): auto open browser when start dev mode #774

Merged
merged 2 commits into from
Apr 10, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions core/docz-core/src/commands/dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { Socket } from '../lib/Socket'
import { parseConfig } from '../config/docz'
import { onSignal } from '../utils/on-signal'
import { bundler as webpack } from '../bundler'
import { openBrowser } from '../utils/open-browser'
import * as states from '../states'

export const dev = async (args: Arguments<any>) => {
Expand Down Expand Up @@ -40,6 +41,7 @@ export const dev = async (args: Arguments<any>) => {

try {
await dataServer.start()
if (args.open || args.o) openBrowser(`http://${config.host}:${config.port}`)
} catch (err) {
logger.fatal('Failed to process data server')
logger.error(err)
Expand Down
6 changes: 6 additions & 0 deletions core/docz-core/src/config/argv.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,4 +203,10 @@ export const setArgs = (yargs: Yargs) => {
type: 'string',
default: getEnv('docz.separator', '-'),
})
.option('open', {
alias: 'o',
describe: 'auto open browser in dev mode',
type: 'boolean',
default: false,
})
}
127 changes: 127 additions & 0 deletions core/docz-core/src/utils/open-browser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/* tslint:disable */
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

'use strict'

var chalk = require('chalk')
var execSync = require('child_process').execSync
var spawn = require('cross-spawn')
var opn = require('opn')

// https://github.com/sindresorhus/opn#app
var OSX_CHROME = 'google chrome'

const Actions = Object.freeze({
NONE: 0,
BROWSER: 1,
SCRIPT: 2,
})

function getBrowserEnv() {
// Attempt to honor this environment variable.
// It is specific to the operating system.
// See https://github.com/sindresorhus/opn#app for documentation.
const value = process.env.BROWSER
let action
if (!value) {
// Default.
action = Actions.BROWSER
} else if (value.toLowerCase().endsWith('.js')) {
action = Actions.SCRIPT
} else if (value.toLowerCase() === 'none') {
action = Actions.NONE
} else {
action = Actions.BROWSER
}
return { action, value }
}

function executeNodeScript(scriptPath: any, url: any) {
const extraArgs = process.argv.slice(2)
const child = spawn('node', [scriptPath, ...extraArgs, url], {
stdio: 'inherit',
})
child.on('close', (code: any) => {
if (code !== 0) {
console.log()
console.log(
chalk.red(
'The script specified as BROWSER environment variable failed.'
)
)
console.log(chalk.cyan(scriptPath) + ' exited with code ' + code + '.')
console.log()
return
}
})
return true
}

function startBrowserProcess(browser: any, url: any) {
// If we're on OS X, the user hasn't specifically
// requested a different browser, we can try opening
// Chrome with AppleScript. This lets us reuse an
// existing tab when possible instead of creating a new one.
const shouldTryOpenChromeWithAppleScript =
process.platform === 'darwin' &&
(typeof browser !== 'string' || browser === OSX_CHROME)

if (shouldTryOpenChromeWithAppleScript) {
try {
// Try our best to reuse existing tab
// on OS X Google Chrome with AppleScript
execSync('ps cax | grep "Google Chrome"')
execSync('osascript openChrome.applescript "' + encodeURI(url) + '"', {
cwd: __dirname,
stdio: 'ignore',
})
return true
} catch (err) {
// Ignore errors.
}
}

// Another special case: on OS X, check if BROWSER has been set to "open".
// In this case, instead of passing `open` to `opn` (which won't work),
// just ignore it (thus ensuring the intended behavior, i.e. opening the system browser):
// https://github.com/facebook/create-react-app/pull/1690#issuecomment-283518768
if (process.platform === 'darwin' && browser === 'open') {
browser = undefined
}

// Fallback to opn
// (It will always open new tab)
try {
var options = { app: browser, wait: false }
opn(url, options).catch(() => {}) // Prevent `unhandledRejection` error.
return true
} catch (err) {
return false
}
}

/**
* Reads the BROWSER environment variable and decides what to do with it. Returns
* true if it opened a browser or ran a node.js script, otherwise false.
*/
export function openBrowser(url: any) {
const { action, value } = getBrowserEnv()
switch (action) {
case Actions.NONE:
// Special case: BROWSER="none" will prevent opening completely.
return false
case Actions.SCRIPT:
return executeNodeScript(value, url)
case Actions.BROWSER:
return startBrowserProcess(value, url)
default:
throw new Error('Not implemented.')
}
}

// module.exports = openBrowser