mirror of
https://github.com/zhigang1992/create-react-app.git
synced 2026-04-24 05:05:53 +08:00
Extract some utilities into a separate package (#723)
* Extract some utilities into a separate package * Add utils dir to `files` in package.json * Do not create an empty `utils` dir on eject
This commit is contained in:
7
packages/react-scripts/scripts/build.js
vendored
7
packages/react-scripts/scripts/build.js
vendored
@@ -27,11 +27,14 @@ var rimrafSync = require('rimraf').sync;
|
||||
var webpack = require('webpack');
|
||||
var config = require('../config/webpack.config.prod');
|
||||
var paths = require('../config/paths');
|
||||
var checkRequiredFiles = require('./utils/checkRequiredFiles');
|
||||
var checkRequiredFiles = require('react-dev-utils/checkRequiredFiles');
|
||||
var recursive = require('recursive-readdir');
|
||||
var stripAnsi = require('strip-ansi');
|
||||
|
||||
checkRequiredFiles();
|
||||
// Warn and crash if required files are missing
|
||||
if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Input: /User/dan/app/build/static/js/main.82be8.js
|
||||
// Output: /static/js/main.js
|
||||
|
||||
14
packages/react-scripts/scripts/eject.js
vendored
14
packages/react-scripts/scripts/eject.js
vendored
@@ -7,10 +7,10 @@
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
var createJestConfig = require('./utils/createJestConfig');
|
||||
var createJestConfig = require('../utils/createJestConfig');
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var prompt = require('./utils/prompt');
|
||||
var prompt = require('react-dev-utils/prompt');
|
||||
var rimrafSync = require('rimraf').sync;
|
||||
var spawnSync = require('cross-spawn').sync;
|
||||
|
||||
@@ -31,6 +31,7 @@ prompt(
|
||||
var files = [
|
||||
'.babelrc',
|
||||
'.eslintrc',
|
||||
path.join('config', 'env.js'),
|
||||
path.join('config', 'paths.js'),
|
||||
path.join('config', 'polyfills.js'),
|
||||
path.join('config', 'webpack.config.dev.js'),
|
||||
@@ -39,13 +40,7 @@ prompt(
|
||||
path.join('config', 'jest', 'FileStub.js'),
|
||||
path.join('scripts', 'build.js'),
|
||||
path.join('scripts', 'start.js'),
|
||||
path.join('scripts', 'test.js'),
|
||||
path.join('scripts', 'utils', 'checkRequiredFiles.js'),
|
||||
path.join('scripts', 'utils', 'chrome.applescript'),
|
||||
path.join('scripts', 'utils', 'getClientEnvironment.js'),
|
||||
path.join('scripts', 'utils', 'InterpolateHtmlPlugin.js'),
|
||||
path.join('scripts', 'utils', 'prompt.js'),
|
||||
path.join('scripts', 'utils', 'WatchMissingNodeModulesPlugin.js')
|
||||
path.join('scripts', 'test.js')
|
||||
];
|
||||
|
||||
// Ensure that the app folder is clean and we won't override any files
|
||||
@@ -65,7 +60,6 @@ prompt(
|
||||
fs.mkdirSync(path.join(appPath, 'config'));
|
||||
fs.mkdirSync(path.join(appPath, 'config', 'jest'));
|
||||
fs.mkdirSync(path.join(appPath, 'scripts'));
|
||||
fs.mkdirSync(path.join(appPath, 'scripts', 'utils'));
|
||||
|
||||
files.forEach(function(file) {
|
||||
console.log('Copying ' + file + ' to ' + appPath);
|
||||
|
||||
116
packages/react-scripts/scripts/start.js
vendored
116
packages/react-scripts/scripts/start.js
vendored
@@ -17,20 +17,25 @@ process.env.NODE_ENV = 'development';
|
||||
// https://github.com/motdotla/dotenv
|
||||
require('dotenv').config({silent: true});
|
||||
|
||||
var path = require('path');
|
||||
var chalk = require('chalk');
|
||||
var webpack = require('webpack');
|
||||
var WebpackDevServer = require('webpack-dev-server');
|
||||
var historyApiFallback = require('connect-history-api-fallback');
|
||||
var httpProxyMiddleware = require('http-proxy-middleware');
|
||||
var execSync = require('child_process').execSync;
|
||||
var opn = require('opn');
|
||||
var detect = require('detect-port');
|
||||
var checkRequiredFiles = require('./utils/checkRequiredFiles');
|
||||
var prompt = require('./utils/prompt');
|
||||
var clearConsole = require('react-dev-utils/clearConsole');
|
||||
var checkRequiredFiles = require('react-dev-utils/checkRequiredFiles');
|
||||
var formatWebpackMessages = require('react-dev-utils/formatWebpackMessages');
|
||||
var openBrowser = require('react-dev-utils/openBrowser');
|
||||
var prompt = require('react-dev-utils/prompt');
|
||||
var config = require('../config/webpack.config.dev');
|
||||
var paths = require('../config/paths');
|
||||
|
||||
// Warn and crash if required files are missing
|
||||
if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Tools like Cloud9 rely on this.
|
||||
var DEFAULT_PORT = process.env.PORT || 3000;
|
||||
var compiler;
|
||||
@@ -49,40 +54,6 @@ if (isSmokeTest) {
|
||||
};
|
||||
}
|
||||
|
||||
// Some custom utilities to prettify Webpack output.
|
||||
// This is a little hacky.
|
||||
// It would be easier if webpack provided a rich error object.
|
||||
var friendlySyntaxErrorLabel = 'Syntax error:';
|
||||
function isLikelyASyntaxError(message) {
|
||||
return message.indexOf(friendlySyntaxErrorLabel) !== -1;
|
||||
}
|
||||
function formatMessage(message) {
|
||||
return message
|
||||
// Make some common errors shorter:
|
||||
.replace(
|
||||
// Babel syntax error
|
||||
'Module build failed: SyntaxError:',
|
||||
friendlySyntaxErrorLabel
|
||||
)
|
||||
.replace(
|
||||
// Webpack file not found error
|
||||
/Module not found: Error: Cannot resolve 'file' or 'directory'/,
|
||||
'Module not found:'
|
||||
)
|
||||
// Internal stacks are generally useless so we strip them
|
||||
.replace(/^\s*at\s.*:\d+:\d+[\s\)]*\n/gm, '') // at ... ...:x:y
|
||||
// Webpack loader names obscure CSS filenames
|
||||
.replace('./~/css-loader!./~/postcss-loader!', '');
|
||||
}
|
||||
|
||||
var isFirstClear = true;
|
||||
function clearConsole() {
|
||||
// On first run, clear completely so it doesn't show half screen on Windows.
|
||||
// On next runs, use a different sequence that properly scrolls back.
|
||||
process.stdout.write(isFirstClear ? '\x1bc' : '\x1b[2J\x1b[0f');
|
||||
isFirstClear = false;
|
||||
}
|
||||
|
||||
function setupCompiler(host, port, protocol) {
|
||||
// "Compiler" is a low-level interface to Webpack.
|
||||
// It lets us listen to some events and provide our own custom messages.
|
||||
@@ -101,9 +72,12 @@ function setupCompiler(host, port, protocol) {
|
||||
// Whether or not you have warnings or errors, you will get this event.
|
||||
compiler.plugin('done', function(stats) {
|
||||
clearConsole();
|
||||
var hasErrors = stats.hasErrors();
|
||||
var hasWarnings = stats.hasWarnings();
|
||||
if (!hasErrors && !hasWarnings) {
|
||||
|
||||
// We have switched off the default Webpack output in WebpackDevServer
|
||||
// options so we are going to "massage" the warnings and errors and present
|
||||
// them in a readable focused way.
|
||||
var messages = formatWebpackMessages(stats);
|
||||
if (!messages.errors.length && !messages.warnings.length) {
|
||||
console.log(chalk.green('Compiled successfully!'));
|
||||
console.log();
|
||||
console.log('The app is running at:');
|
||||
@@ -113,41 +87,24 @@ function setupCompiler(host, port, protocol) {
|
||||
console.log('Note that the development build is not optimized.');
|
||||
console.log('To create a production build, use ' + chalk.cyan('npm run build') + '.');
|
||||
console.log();
|
||||
return;
|
||||
}
|
||||
|
||||
// We have switched off the default Webpack output in WebpackDevServer
|
||||
// options so we are going to "massage" the warnings and errors and present
|
||||
// them in a readable focused way.
|
||||
// We use stats.toJson({}, true) to make output more compact and readable:
|
||||
// https://github.com/facebookincubator/create-react-app/issues/401#issuecomment-238291901
|
||||
var json = stats.toJson({}, true);
|
||||
var formattedErrors = json.errors.map(message =>
|
||||
'Error in ' + formatMessage(message)
|
||||
);
|
||||
var formattedWarnings = json.warnings.map(message =>
|
||||
'Warning in ' + formatMessage(message)
|
||||
);
|
||||
if (hasErrors) {
|
||||
// If errors exist, only show errors.
|
||||
if (messages.errors.length) {
|
||||
console.log(chalk.red('Failed to compile.'));
|
||||
console.log();
|
||||
if (formattedErrors.some(isLikelyASyntaxError)) {
|
||||
// If there are any syntax errors, show just them.
|
||||
// This prevents a confusing ESLint parsing error
|
||||
// preceding a much more useful Babel syntax error.
|
||||
formattedErrors = formattedErrors.filter(isLikelyASyntaxError);
|
||||
}
|
||||
formattedErrors.forEach(message => {
|
||||
messages.errors.forEach(message => {
|
||||
console.log(message);
|
||||
console.log();
|
||||
});
|
||||
// If errors exist, ignore warnings.
|
||||
return;
|
||||
}
|
||||
if (hasWarnings) {
|
||||
|
||||
// Show warnings if no errors were found.
|
||||
if (messages.warnings.length) {
|
||||
console.log(chalk.yellow('Compiled with warnings.'));
|
||||
console.log();
|
||||
formattedWarnings.forEach(message => {
|
||||
messages.warnings.forEach(message => {
|
||||
console.log(message);
|
||||
console.log();
|
||||
});
|
||||
@@ -159,30 +116,6 @@ function setupCompiler(host, port, protocol) {
|
||||
});
|
||||
}
|
||||
|
||||
function openBrowser(host, port, protocol) {
|
||||
if (process.platform === 'darwin') {
|
||||
try {
|
||||
// Try our best to reuse existing tab
|
||||
// on OS X Google Chrome with AppleScript
|
||||
execSync('ps cax | grep "Google Chrome"');
|
||||
execSync(
|
||||
'osascript chrome.applescript ' + protocol + '://' + host + ':' + port + '/',
|
||||
{cwd: path.join(__dirname, 'utils'), stdio: 'ignore'}
|
||||
);
|
||||
return;
|
||||
} catch (err) {
|
||||
// Ignore errors.
|
||||
}
|
||||
}
|
||||
// Fallback to opn
|
||||
// (It will always open new tab)
|
||||
try {
|
||||
opn(protocol + '://' + host + ':' + port + '/');
|
||||
} catch (err) {
|
||||
// Ignore errors.
|
||||
}
|
||||
}
|
||||
|
||||
// We need to provide a custom onError function for httpProxyMiddleware.
|
||||
// It allows us to log custom error messages on the console.
|
||||
function onProxyError(proxy) {
|
||||
@@ -314,14 +247,13 @@ function runDevServer(host, port, protocol) {
|
||||
clearConsole();
|
||||
console.log(chalk.cyan('Starting the development server...'));
|
||||
console.log();
|
||||
openBrowser(host, port, protocol);
|
||||
openBrowser(protocol + '://' + host + ':' + port + '/');
|
||||
});
|
||||
}
|
||||
|
||||
function run(port) {
|
||||
var protocol = process.env.HTTPS === 'true' ? "https" : "http";
|
||||
var host = process.env.HOST || 'localhost';
|
||||
checkRequiredFiles();
|
||||
setupCompiler(host, port, protocol);
|
||||
runDevServer(host, port, protocol);
|
||||
}
|
||||
|
||||
2
packages/react-scripts/scripts/test.js
vendored
2
packages/react-scripts/scripts/test.js
vendored
@@ -28,7 +28,7 @@ if (!process.env.CI) {
|
||||
|
||||
// @remove-on-eject-begin
|
||||
// This is not necessary after eject because we embed config into package.json.
|
||||
const createJestConfig = require('./utils/createJestConfig');
|
||||
const createJestConfig = require('../utils/createJestConfig');
|
||||
const path = require('path');
|
||||
const paths = require('../config/paths');
|
||||
argv.push('--config', JSON.stringify(createJestConfig(
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
// @remove-on-eject-begin
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
// @remove-on-eject-end
|
||||
|
||||
// This Webpack plugin lets us interpolate custom variables into `index.html`.
|
||||
// Usage: `new InterpolateHtmlPlugin({ 'MY_VARIABLE': 42 })`
|
||||
// Then, you can use %MY_VARIABLE% in your `index.html`.
|
||||
|
||||
// It works in tandem with HtmlWebpackPlugin.
|
||||
// Learn more about creating plugins like this:
|
||||
// https://github.com/ampedandwired/html-webpack-plugin#events
|
||||
|
||||
'use strict';
|
||||
|
||||
class InterpolateHtmlPlugin {
|
||||
constructor(replacements) {
|
||||
this.replacements = replacements;
|
||||
}
|
||||
|
||||
apply(compiler) {
|
||||
compiler.plugin('compilation', compilation => {
|
||||
compilation.plugin('html-webpack-plugin-before-html-processing',
|
||||
(data, callback) => {
|
||||
// Run HTML through a series of user-specified string replacements.
|
||||
Object.keys(this.replacements).forEach(key => {
|
||||
const value = this.replacements[key];
|
||||
data.html = data.html.replace('%' + key + '%', value);
|
||||
});
|
||||
callback(null, data);
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = InterpolateHtmlPlugin;
|
||||
@@ -1,35 +0,0 @@
|
||||
// @remove-on-eject-begin
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
// @remove-on-eject-end
|
||||
|
||||
// This Webpack plugin ensures `npm install <library>` forces a project rebuild.
|
||||
// We’re not sure why this isn't Webpack's default behavior.
|
||||
// See https://github.com/facebookincubator/create-react-app/issues/186.
|
||||
|
||||
function WatchMissingNodeModulesPlugin(nodeModulesPath) {
|
||||
this.nodeModulesPath = nodeModulesPath;
|
||||
}
|
||||
|
||||
WatchMissingNodeModulesPlugin.prototype.apply = function (compiler) {
|
||||
compiler.plugin('emit', (compilation, callback) => {
|
||||
var missingDeps = compilation.missingDependencies;
|
||||
var nodeModulesPath = this.nodeModulesPath;
|
||||
|
||||
// If any missing files are expected to appear in node_modules...
|
||||
if (missingDeps.some(file => file.indexOf(nodeModulesPath) !== -1)) {
|
||||
// ...tell webpack to watch node_modules recursively until they appear.
|
||||
compilation.contextDependencies.push(nodeModulesPath);
|
||||
}
|
||||
|
||||
callback();
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = WatchMissingNodeModulesPlugin;
|
||||
@@ -1,33 +0,0 @@
|
||||
// @remove-on-eject-begin
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
// @remove-on-eject-end
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const chalk = require('chalk');
|
||||
const paths = require('../../config/paths');
|
||||
|
||||
function checkRequiredFiles() {
|
||||
const filesPathToCheck = [paths.appHtml, paths.appIndexJs];
|
||||
filesPathToCheck.forEach(filePath => {
|
||||
try {
|
||||
fs.accessSync(filePath, fs.F_OK);
|
||||
} catch (err) {
|
||||
const dirName = path.dirname(filePath);
|
||||
const fileName = path.basename(filePath);
|
||||
console.log(chalk.red('Could not find a required file.'));
|
||||
console.log(chalk.red(' Name: ') + chalk.cyan(fileName));
|
||||
console.log(chalk.red(' Searched in: ') + chalk.cyan(dirName));
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = checkRequiredFiles;
|
||||
@@ -1,50 +0,0 @@
|
||||
-- @remove-on-eject-begin
|
||||
(*
|
||||
Copyright (c) 2015-present, Facebook, Inc.
|
||||
All rights reserved.
|
||||
|
||||
This source code is licensed under the BSD-style license found in the
|
||||
-- LICENSE file in the root directory of this source tree. An additional grant
|
||||
of patent rights can be found in the PATENTS file in the same directory.
|
||||
*)
|
||||
-- @remove-on-eject-end
|
||||
|
||||
on run argv
|
||||
set theURL to item 1 of argv
|
||||
|
||||
tell application "Chrome"
|
||||
|
||||
if (count every window) = 0 then
|
||||
make new window
|
||||
end if
|
||||
|
||||
-- Find a tab currently running the debugger
|
||||
set found to false
|
||||
set theTabIndex to -1
|
||||
repeat with theWindow in every window
|
||||
set theTabIndex to 0
|
||||
repeat with theTab in every tab of theWindow
|
||||
set theTabIndex to theTabIndex + 1
|
||||
if theTab's URL is theURL then
|
||||
set found to true
|
||||
exit repeat
|
||||
end if
|
||||
end repeat
|
||||
|
||||
if found then
|
||||
exit repeat
|
||||
end if
|
||||
end repeat
|
||||
|
||||
if found then
|
||||
tell theTab to reload
|
||||
set index of theWindow to 1
|
||||
set theWindow's active tab index to theTabIndex
|
||||
else
|
||||
tell window 1
|
||||
activate
|
||||
make new tab with properties {URL:theURL}
|
||||
end tell
|
||||
end if
|
||||
end tell
|
||||
end run
|
||||
@@ -1,43 +0,0 @@
|
||||
// @remove-on-eject-begin
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
// @remove-on-eject-end
|
||||
|
||||
const pathExists = require('path-exists');
|
||||
const paths = require('../../config/paths');
|
||||
|
||||
module.exports = (resolve, rootDir, isEjecting) => {
|
||||
const setupFiles = [resolve('config/polyfills.js')];
|
||||
if (pathExists.sync(paths.testsSetup)) {
|
||||
// Use this instead of `paths.testsSetup` to avoid putting
|
||||
// an absolute filename into configuration after ejecting.
|
||||
setupFiles.push('<rootDir>/src/setupTests.js');
|
||||
}
|
||||
|
||||
const config = {
|
||||
moduleFileExtensions: ['jsx', 'js', 'json'],
|
||||
moduleNameMapper: {
|
||||
'^.+\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': resolve('config/jest/FileStub.js'),
|
||||
'^.+\\.css$': resolve('config/jest/CSSStub.js')
|
||||
},
|
||||
setupFiles: setupFiles,
|
||||
testPathIgnorePatterns: ['<rootDir>/(build|docs|node_modules)/'],
|
||||
testEnvironment: 'node',
|
||||
testRegex: '(/__tests__/.*|\\.(test|spec))\\.(js|jsx)$',
|
||||
};
|
||||
if (rootDir) {
|
||||
config.rootDir = rootDir;
|
||||
}
|
||||
if (!isEjecting) {
|
||||
// This is unnecessary after ejecting because Jest
|
||||
// will just use .babelrc in the project folder.
|
||||
config.scriptPreprocessor = resolve('config/jest/transform.js');
|
||||
}
|
||||
return config;
|
||||
};
|
||||
@@ -1,38 +0,0 @@
|
||||
// @remove-on-eject-begin
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
// @remove-on-eject-end
|
||||
|
||||
// Grab NODE_ENV and REACT_APP_* environment variables and prepare them to be
|
||||
// injected into the application via DefinePlugin in Webpack configuration.
|
||||
|
||||
var REACT_APP = /^REACT_APP_/i;
|
||||
|
||||
function getClientEnvironment(publicUrl) {
|
||||
return Object
|
||||
.keys(process.env)
|
||||
.filter(key => REACT_APP.test(key))
|
||||
.reduce((env, key) => {
|
||||
env['process.env.' + key] = JSON.stringify(process.env[key]);
|
||||
return env;
|
||||
}, {
|
||||
// Useful for determining whether we’re running in production mode.
|
||||
// Most importantly, it switches React into the correct mode.
|
||||
'process.env.NODE_ENV': JSON.stringify(
|
||||
process.env.NODE_ENV || 'development'
|
||||
),
|
||||
// Useful for resolving the correct path to static assets in `public`.
|
||||
// For example, <img src={process.env.PUBLIC_URL + '/img/logo.png'} />.
|
||||
// This should only be used as an escape hatch. Normally you would put
|
||||
// images into the `src` and `import` them in code to get their paths.
|
||||
'process.env.PUBLIC_URL': JSON.stringify(publicUrl)
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = getClientEnvironment;
|
||||
42
packages/react-scripts/scripts/utils/prompt.js
vendored
42
packages/react-scripts/scripts/utils/prompt.js
vendored
@@ -1,42 +0,0 @@
|
||||
// @remove-on-eject-begin
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
// @remove-on-eject-end
|
||||
|
||||
var rl = require('readline');
|
||||
|
||||
// Convention: "no" should be the conservative choice.
|
||||
// If you mistype the answer, we'll always take it as a "no".
|
||||
// You can control the behavior on <Enter> with `isYesDefault`.
|
||||
module.exports = function (question, isYesDefault) {
|
||||
if (typeof isYesDefault !== 'boolean') {
|
||||
throw new Error('Provide explicit boolean isYesDefault as second argument.');
|
||||
}
|
||||
return new Promise(resolve => {
|
||||
var rlInterface = rl.createInterface({
|
||||
input: process.stdin,
|
||||
output: process.stdout,
|
||||
});
|
||||
|
||||
var hint = isYesDefault === true ? '[Y/n]' : '[y/N]';
|
||||
var message = question + ' ' + hint + '\n';
|
||||
|
||||
rlInterface.question(message, function(answer) {
|
||||
rlInterface.close();
|
||||
|
||||
var useDefault = answer.trim().length === 0;
|
||||
if (useDefault) {
|
||||
return resolve(isYesDefault);
|
||||
}
|
||||
|
||||
var isYes = answer.match(/^(yes|y)$/i);
|
||||
return resolve(isYes);
|
||||
});
|
||||
});
|
||||
};
|
||||
Reference in New Issue
Block a user