1
+ /**
2
+ * Copyright (c) 2015-present, Facebook, Inc.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ 'use strict' ;
9
+
10
+ var chalk = require ( 'colors-cli' ) ;
11
+ var execSync = require ( 'child_process' ) . execSync ;
12
+ var spawn = require ( 'cross-spawn' ) ;
13
+ var opn = require ( 'opn' ) ;
14
+
15
+ // https://github.com/sindresorhus/opn#app
16
+ var OSX_CHROME = 'google chrome' ;
17
+
18
+ const Actions = Object . freeze ( {
19
+ NONE : 0 ,
20
+ BROWSER : 1 ,
21
+ SCRIPT : 2 ,
22
+ } ) ;
23
+
24
+ function getBrowserEnv ( ) {
25
+ // Attempt to honor this environment variable.
26
+ // It is specific to the operating system.
27
+ // See https://github.com/sindresorhus/opn#app for documentation.
28
+ const value = process . env . BROWSER ;
29
+ let action ;
30
+ if ( ! value ) {
31
+ // Default.
32
+ action = Actions . BROWSER ;
33
+ } else if ( value . toLowerCase ( ) . endsWith ( '.js' ) ) {
34
+ action = Actions . SCRIPT ;
35
+ } else if ( value . toLowerCase ( ) === 'none' ) {
36
+ action = Actions . NONE ;
37
+ } else {
38
+ action = Actions . BROWSER ;
39
+ }
40
+ return { action, value } ;
41
+ }
42
+
43
+ function executeNodeScript ( scriptPath , url ) {
44
+ const extraArgs = process . argv . slice ( 2 ) ;
45
+ const child = spawn ( 'node' , [ scriptPath , ...extraArgs , url ] , {
46
+ stdio : 'inherit' ,
47
+ } ) ;
48
+ child . on ( 'close' , code => {
49
+ if ( code !== 0 ) {
50
+ console . log ( ) ;
51
+ console . log (
52
+ chalk . red (
53
+ 'The script specified as BROWSER environment variable failed.'
54
+ )
55
+ ) ;
56
+ console . log ( chalk . cyan ( scriptPath ) + ' exited with code ' + code + '.' ) ;
57
+ console . log ( ) ;
58
+ return ;
59
+ }
60
+ } ) ;
61
+ return true ;
62
+ }
63
+
64
+ function startBrowserProcess ( browser , url ) {
65
+ // If we're on OS X, the user hasn't specifically
66
+ // requested a different browser, we can try opening
67
+ // Chrome with AppleScript. This lets us reuse an
68
+ // existing tab when possible instead of creating a new one.
69
+ const shouldTryOpenChromeWithAppleScript =
70
+ process . platform === 'darwin' &&
71
+ ( typeof browser !== 'string' || browser === OSX_CHROME ) ;
72
+
73
+ if ( shouldTryOpenChromeWithAppleScript ) {
74
+ try {
75
+ // Try our best to reuse existing tab
76
+ // on OS X Google Chrome with AppleScript
77
+ execSync ( 'ps cax | grep "Google Chrome"' ) ;
78
+ execSync ( 'osascript openChrome.applescript "' + encodeURI ( url ) + '"' , {
79
+ cwd : __dirname ,
80
+ stdio : 'ignore' ,
81
+ } ) ;
82
+ return true ;
83
+ } catch ( err ) {
84
+ // Ignore errors.
85
+ }
86
+ }
87
+
88
+ // Another special case: on OS X, check if BROWSER has been set to "open".
89
+ // In this case, instead of passing `open` to `opn` (which won't work),
90
+ // just ignore it (thus ensuring the intended behavior, i.e. opening the system browser):
91
+ // https://github.com/facebook/create-react-app/pull/1690#issuecomment-283518768
92
+ if ( process . platform === 'darwin' && browser === 'open' ) {
93
+ browser = undefined ;
94
+ }
95
+
96
+ // Fallback to opn
97
+ // (It will always open new tab)
98
+ try {
99
+ var options = { app : browser } ;
100
+ opn ( url , options ) . catch ( ( ) => { } ) ; // Prevent `unhandledRejection` error.
101
+ return true ;
102
+ } catch ( err ) {
103
+ return false ;
104
+ }
105
+ }
106
+
107
+ /**
108
+ * Reads the BROWSER evironment variable and decides what to do with it. Returns
109
+ * true if it opened a browser or ran a node.js script, otherwise false.
110
+ */
111
+ function openBrowser ( url ) {
112
+ const { action, value } = getBrowserEnv ( ) ;
113
+ switch ( action ) {
114
+ case Actions . NONE :
115
+ // Special case: BROWSER="none" will prevent opening completely.
116
+ return false ;
117
+ case Actions . SCRIPT :
118
+ return executeNodeScript ( value , url ) ;
119
+ case Actions . BROWSER :
120
+ return startBrowserProcess ( value , url ) ;
121
+ default :
122
+ throw new Error ( 'Not implemented.' ) ;
123
+ }
124
+ }
125
+
126
+ module . exports = openBrowser ;
0 commit comments