UNPKG

4.37 kBJavaScriptView Raw
1/**
2 * @fileoverview Config initialization wizard.
3 * @author Ilya Volodin
4 * @copyright 2015 Ilya Volodin. All rights reserved.
5 */
6
7"use strict";
8
9var exec = require("child_process").exec,
10 fs = require("fs"),
11 inquirer = require("inquirer"),
12 yaml = require("js-yaml");
13
14/* istanbul ignore next: hard to test fs function */
15/**
16 * Create .eslintrc file in the current working directory
17 * @param {object} config object that contains user's answers
18 * @param {bool} isJson should config file be json or yaml
19 * @param {function} callback function to call once the file is written.
20 * @returns {void}
21 */
22function writeFile(config, isJson, callback) {
23 try {
24 fs.writeFileSync("./.eslintrc", isJson ? JSON.stringify(config, null, 4) : yaml.safeDump(config));
25 } catch (e) {
26 callback(e);
27 return;
28 }
29 if (config.plugins && config.plugins.indexOf("react") >= 0) {
30 exec("npm i eslint-plugin-react --save-dev", callback);
31 return;
32 }
33 callback();
34}
35
36/**
37 * process user's answers and create config object
38 * @param {object} answers answers received from inquirer
39 * @returns {object} config object
40 */
41function processAnswers(answers) {
42 var config = {rules: {}, env: {}, extends: "eslint:recommended"};
43 config.rules.indent = [2, answers.indent];
44 config.rules.quotes = [2, answers.quotes];
45 config.rules["linebreak-style"] = [2, answers.linebreak];
46 config.rules.semi = [2, answers.semi ? "always" : "never"];
47 if (answers.es6) {
48 config.env.es6 = true;
49 }
50 answers.env.forEach(function(env) {
51 config.env[env] = true;
52 });
53 if (answers.jsx) {
54 config.ecmaFeatures = {jsx: true};
55 if (answers.react) {
56 config.plugins = ["react"];
57 config.ecmaFeatures.experimentalObjectRestSpread = true;
58 }
59 }
60 return config;
61}
62
63/* istanbul ignore next: no need to test inquirer*/
64/**
65 * Ask use a few questions on command prompt
66 * @param {function} callback callback function when file has been written
67 * @returns {void}
68 */
69function promptUser(callback) {
70 inquirer.prompt([
71 {
72 type: "list",
73 name: "indent",
74 message: "What style of indentation do you use?",
75 default: "tabs",
76 choices: [{name: "Tabs", value: "tab"}, {name: "Spaces", value: 4}]
77 },
78 {
79 type: "list",
80 name: "quotes",
81 message: "What quotes do you use for strings?",
82 default: "double",
83 choices: [{name: "Double", value: "double"}, {name: "Single", value: "single"}]
84 },
85 {
86 type: "list",
87 name: "linebreak",
88 message: "What line endings do you use?",
89 default: "unix",
90 choices: [{name: "Unix", value: "unix"}, {name: "Windows", value: "windows"}]
91 },
92 {
93 type: "confirm",
94 name: "semi",
95 message: "Do you require semicolons?",
96 default: true
97 },
98 {
99 type: "confirm",
100 name: "es6",
101 message: "Are you using ECMAScript 6 features?",
102 default: false
103 },
104 {
105 type: "checkbox",
106 name: "env",
107 message: "Where will your code run?",
108 default: ["browser"],
109 choices: [{name: "Node", value: "node"}, {name: "Browser", value: "browser"}]
110 },
111 {
112 type: "confirm",
113 name: "jsx",
114 message: "Do you use JSX?",
115 default: false
116 },
117 {
118 type: "confirm",
119 name: "react",
120 message: "Do you use React",
121 default: false,
122 when: function(answers) {
123 return answers.jsx;
124 }
125 },
126 {
127 type: "list",
128 name: "format",
129 message: "What format do you want your config file to be in?",
130 default: "JSON",
131 choices: ["JSON", "YAML"]
132 }
133 ], function(answers) {
134 var config = processAnswers(answers);
135 writeFile(config, answers.format === "JSON", callback);
136 });
137}
138
139var init = {
140 processAnswers: processAnswers,
141 initializeConfig: /* istanbul ignore next */ function(callback) {
142 promptUser(callback);
143 }
144};
145
146module.exports = init;