@@ -7,7 +7,7 @@ import path from "path";
7
7
import { spawnSync } from "child_process" ;
8
8
import { writeFile } from "fs/promises" ;
9
9
import enquirer from "enquirer" ;
10
- import { isPackageTypeModule , installSyncSaveDev } from "./utils/npm-utils.js" ;
10
+ import { isPackageTypeModule , installSyncSaveDev , checkPackageJson } from "./utils/npm-utils.js" ;
11
11
import * as log from "./utils/logging.js" ;
12
12
13
13
/**
@@ -36,16 +36,94 @@ export class ConfigGenerator {
36
36
* Prompt the user for input.
37
37
* @returns {void }
38
38
*/
39
- prompt ( ) {
40
-
41
- // TODO: ask users to input
42
- this . answers = {
43
- purpose : "syntax" ,
44
- module : "esm" ,
45
- framework : "vue" ,
46
- lang : "js" ,
47
- env : [ "browser" , "node" ]
48
- } ;
39
+ async prompt ( ) {
40
+ const packageJsonExists = checkPackageJson ( this . cwd ) ;
41
+
42
+ if ( ! packageJsonExists ) {
43
+ throw new Error ( "A package.json file is necessary to initialize ESLint. Run `npm init` to create a package.json file and try again." ) ;
44
+ }
45
+
46
+ const questions = [
47
+ {
48
+ type : "select" ,
49
+ name : "purpose" ,
50
+ message : "How would you like to use ESLint?" ,
51
+ initial : 1 ,
52
+ choices : [
53
+ { message : "To check syntax only" , name : "syntax" } ,
54
+ { message : "To check syntax and find problems" , name : "problems" } ,
55
+ { message : "To check syntax, find problems, and enforce code style" , name : "style" }
56
+ ]
57
+ } ,
58
+ {
59
+ type : "select" ,
60
+ name : "moduleType" ,
61
+ message : "What type of modules does your project use?" ,
62
+ initial : 0 ,
63
+ choices : [
64
+ { message : "JavaScript modules (import/export)" , name : "esm" } ,
65
+ { message : "CommonJS (require/exports)" , name : "commonjs" } ,
66
+ { message : "None of these" , name : "none" }
67
+ ]
68
+ } ,
69
+ {
70
+ type : "select" ,
71
+ name : "framework" ,
72
+ message : "Which framework does your project use?" ,
73
+ initial : 0 ,
74
+ choices : [
75
+ { message : "React" , name : "react" } ,
76
+ { message : "Vue.js" , name : "vue" } ,
77
+ { message : "None of these" , name : "none" }
78
+ ]
79
+ } ,
80
+ {
81
+ type : "select" ,
82
+ name : "language" ,
83
+ message : "Does your project use TypeScript?" ,
84
+ choices : [
85
+ { message : "No" , name : "javascript" } ,
86
+ { message : "Yes" , name : "typescript" }
87
+ ] ,
88
+ initial : 0
89
+ } ,
90
+ {
91
+ type : "multiselect" ,
92
+ name : "env" ,
93
+ message : "Where does your code run?" ,
94
+ hint : "(Press <space> to select, <a> to toggle all, <i> to invert selection)" ,
95
+ initial : 0 ,
96
+ choices : [
97
+ { message : "Browser" , name : "browser" } ,
98
+ { message : "Node" , name : "node" }
99
+ ]
100
+ }
101
+ ] ;
102
+
103
+ const answers = await enquirer . prompt ( questions ) ;
104
+
105
+ Object . assign ( this . answers , answers ) ;
106
+
107
+ if ( this . answers . purpose === "style" ) {
108
+
109
+ const jsStyleGuides = [
110
+ { message : "Airbnb: https://github.com/airbnb/javascript" , name : "eslint-config-airbnb" } ,
111
+ { message : "Standard: https://github.com/standard/standard" , name : "staeslint-config-standard" } ,
112
+ { message : "XO: https://github.com/xojs/eslint-config-xo" , name : "eslint-config-xo" }
113
+ ] ;
114
+ const tsStyleGuides = [
115
+ { message : "Standard: https://github.com/standard/eslint-config-standard-with-typescript" , name : "eslint-config-standard-with-typescript" } ,
116
+ { message : "XO: https://github.com/xojs/eslint-config-xo-typescript" , name : "eslint-config-xo-typescript" }
117
+ ] ;
118
+ const styleguideAnswer = await enquirer . prompt ( {
119
+ type : "select" ,
120
+ name : "styleguide" ,
121
+ message : "Which style guide do you want to follow?" ,
122
+ choices : this . answers . language === "javascript" ? jsStyleGuides : tsStyleGuides
123
+ } ) ;
124
+
125
+ Object . assign ( this . answers , styleguideAnswer ) ;
126
+ }
49
127
}
50
128
51
129
// eslint-disable-next-line jsdoc/require-throws -- ts is not supported yet
@@ -112,7 +190,21 @@ export class ConfigGenerator {
112
190
exportContent += " pluginReactConfig,\n" ;
113
191
}
114
192
115
- this . result . configContent = `${ importContent } export default [\n { ${ languageOptionsContent } },\n${ exportContent } ];` ;
193
+ if ( this . answers . styleguide ) {
194
+ this . result . devDependencies . push ( this . answers . styleguide , "@eslint/js" ) ;
195
+ importContent += "import pluginJs from \"@eslint/js\";\n" ;
196
+
197
+ // importContent += `import styleguide from "${this.answers.styleguide}";\n`;
198
+ importContent += "import path from \"path\";\nimport { fileURLToPath } from \"url\";\n" ;
199
+ importContent += "// mimic CommonJS variables -- not needed if using CommonJS\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\n" ;
200
+ importContent += "const compat = new FlatCompat({baseDirectory: __dirname, recommendedConfig: pluginJs.configs.recommended});\n" ;
201
+
202
+ const extendedName = this . answers . styleguide . replace ( "eslint-config-" , "" ) ;
203
+
204
+ exportContent += ` compat.extends("${ extendedName } "),\n` ;
205
+ }
206
+
207
+ this . result . configContent = `${ importContent } export default [].concat(\n { ${ languageOptionsContent } },\n${ exportContent } );` ;
116
208
}
117
209
118
210
/**
0 commit comments