Skip to content

Commit f607c76

Browse files
nzakasaladdin-add
andauthored
feat: Output defineConfig in file (#156)
* feat: Output defineConfig in file * Update lib/config-generator.js Co-authored-by: 唯然 <[email protected]> * Update snapshots * Update file extensions on configs --------- Co-authored-by: 唯然 <[email protected]>
1 parent 2b5411e commit f607c76

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+422
-379
lines changed

lib/config-generator.js

Lines changed: 57 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22
* @fileoverview to generate config files.
33
* @author 唯然<[email protected]>
44
*/
5+
6+
//-----------------------------------------------------------------------------
7+
// Imports
8+
//-----------------------------------------------------------------------------
9+
510
import process from "node:process";
611
import path from "node:path";
712
import { spawnSync } from "node:child_process";
@@ -11,6 +16,41 @@ import { isPackageTypeModule, installSyncSaveDev, fetchPeerDependencies, findPac
1116
import { getShorthandName } from "./utils/naming.js";
1217
import * as log from "./utils/logging.js";
1318

19+
//-----------------------------------------------------------------------------
20+
// Helpers
21+
//-----------------------------------------------------------------------------
22+
23+
/**
24+
* Get the file extensions to lint based on the user's answers.
25+
* @param {Object} answers The answers provided by the user.
26+
* @returns {string[]} The file extensions to lint.
27+
*/
28+
function getExtensions(answers) {
29+
const extensions = ["js", "mjs", "cjs"];
30+
31+
if (answers.language === "typescript") {
32+
extensions.push("ts");
33+
}
34+
35+
if (answers.framework === "vue") {
36+
extensions.push("vue");
37+
}
38+
39+
if (answers.framework === "react") {
40+
extensions.push("jsx");
41+
42+
if (answers.language === "typescript") {
43+
extensions.push("tsx");
44+
}
45+
}
46+
47+
return extensions;
48+
}
49+
50+
//-----------------------------------------------------------------------------
51+
// Exports
52+
//-----------------------------------------------------------------------------
53+
1454
/**
1555
* Class representing a ConfigGenerator.
1656
*/
@@ -112,24 +152,24 @@ export class ConfigGenerator {
112152
this.answers.config = typeof this.answers.config === "string"
113153
? { packageName: this.answers.config, type: "flat" }
114154
: this.answers.config;
115-
const extensions = []; // file extensions to lint, the default is ["js", "mjs", "cjs"]
155+
const extensions = `**/*.{${getExtensions(this.answers)}}`;
116156

117-
let importContent = "";
118-
const helperContent = `import path from "path";
119-
import { fileURLToPath } from "url";
157+
let importContent = "import { defineConfig } from \"eslint/config\";\n";
158+
const helperContent = `import path from "node:path";
159+
import { fileURLToPath } from "node:url";
120160
import { FlatCompat } from "@eslint/eslintrc";
121-
import pluginJs from "@eslint/js";
161+
import js from "@eslint/js";
122162
123163
// mimic CommonJS variables -- not needed if using CommonJS
124164
const __filename = fileURLToPath(import.meta.url);
125165
const __dirname = path.dirname(__filename);
126-
const compat = new FlatCompat({baseDirectory: __dirname, recommendedConfig: pluginJs.configs.recommended});
166+
const compat = new FlatCompat({baseDirectory: __dirname, recommendedConfig: js.configs.recommended});
127167
`;
128168
let exportContent = "";
129169
let needCompatHelper = false;
130170

131171
if (this.answers.moduleType === "commonjs" || this.answers.moduleType === "script") {
132-
exportContent += ` {files: ["**/*.js"], languageOptions: {sourceType: "${this.answers.moduleType}"}},\n`;
172+
exportContent += ` { files: ["**/*.js"], languageOptions: { sourceType: "${this.answers.moduleType}" } },\n`;
133173
}
134174

135175
if (this.answers.env?.length > 0) {
@@ -141,44 +181,36 @@ const compat = new FlatCompat({baseDirectory: __dirname, recommendedConfig: plug
141181
"browser,node": "globals: {...globals.browser, ...globals.node}"
142182
};
143183

144-
exportContent += ` {languageOptions: { ${envContent[this.answers.env.join(",")]} }},\n`;
184+
exportContent += ` { files: ["${extensions}"], languageOptions: { ${envContent[this.answers.env.join(",")]} } },\n`;
145185
}
146186

147187
if (this.answers.purpose === "syntax") {
148188

149189
// no need to install any plugin
150190
} else if (this.answers.purpose === "problems") {
151191
this.result.devDependencies.push("@eslint/js");
152-
importContent += "import pluginJs from \"@eslint/js\";\n";
153-
exportContent += " pluginJs.configs.recommended,\n";
192+
importContent += "import js from \"@eslint/js\";\n";
193+
exportContent += ` { files: ["${extensions}"], plugins: { js }, extends: ["js/recommended"] },\n`;
154194
}
155195

156196
if (this.answers.language === "typescript") {
157-
extensions.push("ts");
158197
this.result.devDependencies.push("typescript-eslint");
159198
importContent += "import tseslint from \"typescript-eslint\";\n";
160-
exportContent += " ...tseslint.configs.recommended,\n";
199+
exportContent += " tseslint.configs.recommended,\n";
161200
}
162201

163202
if (this.answers.framework === "vue") {
164-
extensions.push("vue");
165203
this.result.devDependencies.push("eslint-plugin-vue");
166204
importContent += "import pluginVue from \"eslint-plugin-vue\";\n";
167-
exportContent += " ...pluginVue.configs[\"flat/essential\"],\n";
205+
exportContent += " pluginVue.configs[\"flat/essential\"],\n";
168206

169207
// https://eslint.vuejs.org/user-guide/#how-to-use-a-custom-parser
170208
if (this.answers.language === "typescript") {
171-
exportContent += " {files: [\"**/*.vue\"], languageOptions: {parserOptions: {parser: tseslint.parser}}},\n";
209+
exportContent += " { files: [\"**/*.vue\"], languageOptions: { parserOptions: { parser: tseslint.parser } } },\n";
172210
}
173211
}
174212

175213
if (this.answers.framework === "react") {
176-
extensions.push("jsx");
177-
178-
if (this.answers.language === "typescript") {
179-
extensions.push("tsx");
180-
}
181-
182214
this.result.devDependencies.push("eslint-plugin-react");
183215
importContent += "import pluginReact from \"eslint-plugin-react\";\n";
184216
exportContent += " pluginReact.configs.flat.recommended,\n";
@@ -210,28 +242,27 @@ const compat = new FlatCompat({baseDirectory: __dirname, recommendedConfig: plug
210242

211243
if (config.type === "flat" || config.type === void 0) {
212244
importContent += `import config from "${config.packageName}";\n`;
213-
exportContent += " ...[].concat(config),\n";
245+
exportContent += " config,\n";
214246
} else if (config.type === "eslintrc") {
215247
needCompatHelper = true;
216248

217249
const shorthandName = getShorthandName(config.packageName, "eslint-config");
218250

219-
exportContent += ` ...compat.extends("${shorthandName}"),\n`;
251+
exportContent += ` compat.extends("${shorthandName}"),\n`;
220252
}
221253
}
222254

223255
if (needCompatHelper) {
224256
this.result.devDependencies.push("@eslint/eslintrc", "@eslint/js");
225257
}
226258

227-
const lintFilesConfig = extensions.length > 0 ? ` {files: ["**/*.{${["js", "mjs", "cjs", ...extensions]}}"]},\n` : "";
259+
const lintFilesConfig = ` { files: ["${extensions}"] },\n`;
228260

229261
exportContent = `${lintFilesConfig}${exportContent}`;
230262

231263
this.result.configContent = `${importContent}
232264
${needCompatHelper ? helperContent : ""}
233-
/** @type {import('eslint').Linter.Config[]} */
234-
export default [\n${exportContent || " {}\n"}];`; // defaults to `[{}]` to avoid empty config warning
265+
export default defineConfig([\n${exportContent || " {}\n"}]);`; // defaults to `[{}]` to avoid empty config warning
235266
}
236267

237268
/**

tests/__snapshots__/config@eslint-config-airbnb

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
11
{
2-
"configContent": "
3-
import path from "path";
4-
import { fileURLToPath } from "url";
2+
"configContent": "import { defineConfig } from "eslint/config";
3+
4+
import path from "node:path";
5+
import { fileURLToPath } from "node:url";
56
import { FlatCompat } from "@eslint/eslintrc";
6-
import pluginJs from "@eslint/js";
7+
import js from "@eslint/js";
78

89
// mimic CommonJS variables -- not needed if using CommonJS
910
const __filename = fileURLToPath(import.meta.url);
1011
const __dirname = path.dirname(__filename);
11-
const compat = new FlatCompat({baseDirectory: __dirname, recommendedConfig: pluginJs.configs.recommended});
12+
const compat = new FlatCompat({baseDirectory: __dirname, recommendedConfig: js.configs.recommended});
1213

13-
/** @type {import('eslint').Linter.Config[]} */
14-
export default [
15-
...compat.extends("airbnb"),
16-
];",
14+
export default defineConfig([
15+
{ files: ["**/*.{js,mjs,cjs}"] },
16+
compat.extends("airbnb"),
17+
]);",
1718
"configFilename": "eslint.config.mjs",
1819
"devDependencies": [
1920
"eslint@^7.32.0 || ^8.2.0",

tests/__snapshots__/config@eslint-config-airbnb-base

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
11
{
2-
"configContent": "
3-
import path from "path";
4-
import { fileURLToPath } from "url";
2+
"configContent": "import { defineConfig } from "eslint/config";
3+
4+
import path from "node:path";
5+
import { fileURLToPath } from "node:url";
56
import { FlatCompat } from "@eslint/eslintrc";
6-
import pluginJs from "@eslint/js";
7+
import js from "@eslint/js";
78

89
// mimic CommonJS variables -- not needed if using CommonJS
910
const __filename = fileURLToPath(import.meta.url);
1011
const __dirname = path.dirname(__filename);
11-
const compat = new FlatCompat({baseDirectory: __dirname, recommendedConfig: pluginJs.configs.recommended});
12+
const compat = new FlatCompat({baseDirectory: __dirname, recommendedConfig: js.configs.recommended});
1213

13-
/** @type {import('eslint').Linter.Config[]} */
14-
export default [
15-
...compat.extends("airbnb-base"),
16-
];",
14+
export default defineConfig([
15+
{ files: ["**/*.{js,mjs,cjs}"] },
16+
compat.extends("airbnb-base"),
17+
]);",
1718
"configFilename": "eslint.config.mjs",
1819
"devDependencies": [
1920
"eslint@^7.32.0 || ^8.2.0",

tests/__snapshots__/config@eslint-config-standard

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
11
{
2-
"configContent": "
3-
import path from "path";
4-
import { fileURLToPath } from "url";
2+
"configContent": "import { defineConfig } from "eslint/config";
3+
4+
import path from "node:path";
5+
import { fileURLToPath } from "node:url";
56
import { FlatCompat } from "@eslint/eslintrc";
6-
import pluginJs from "@eslint/js";
7+
import js from "@eslint/js";
78

89
// mimic CommonJS variables -- not needed if using CommonJS
910
const __filename = fileURLToPath(import.meta.url);
1011
const __dirname = path.dirname(__filename);
11-
const compat = new FlatCompat({baseDirectory: __dirname, recommendedConfig: pluginJs.configs.recommended});
12+
const compat = new FlatCompat({baseDirectory: __dirname, recommendedConfig: js.configs.recommended});
1213

13-
/** @type {import('eslint').Linter.Config[]} */
14-
export default [
15-
...compat.extends("standard"),
16-
];",
14+
export default defineConfig([
15+
{ files: ["**/*.{js,mjs,cjs}"] },
16+
compat.extends("standard"),
17+
]);",
1718
"configFilename": "eslint.config.mjs",
1819
"devDependencies": [
1920
"eslint@^8.0.1",

tests/__snapshots__/config@eslint-config-standard-flat

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
{
2-
"configContent": "import config from "eslint-config-standard";
2+
"configContent": "import { defineConfig } from "eslint/config";
3+
import config from "eslint-config-standard";
34

45

5-
/** @type {import('eslint').Linter.Config[]} */
6-
export default [
7-
...[].concat(config),
8-
];",
6+
export default defineConfig([
7+
{ files: ["**/*.{js,mjs,cjs}"] },
8+
config,
9+
]);",
910
"configFilename": "eslint.config.mjs",
1011
"devDependencies": [
1112
"eslint@^8.0.1",

tests/__snapshots__/config@eslint-config-standard-flat2

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
{
2-
"configContent": "import config from "eslint-config-standard";
2+
"configContent": "import { defineConfig } from "eslint/config";
3+
import config from "eslint-config-standard";
34

45

5-
/** @type {import('eslint').Linter.Config[]} */
6-
export default [
7-
...[].concat(config),
8-
];",
6+
export default defineConfig([
7+
{ files: ["**/*.{js,mjs,cjs}"] },
8+
config,
9+
]);",
910
"configFilename": "eslint.config.mjs",
1011
"devDependencies": [
1112
"eslint@^8.0.1",

tests/__snapshots__/config@eslint-config-xo

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
{
2-
"configContent": "import config from "eslint-config-xo";
2+
"configContent": "import { defineConfig } from "eslint/config";
3+
import config from "eslint-config-xo";
34

45

5-
/** @type {import('eslint').Linter.Config[]} */
6-
export default [
7-
...[].concat(config),
8-
];",
6+
export default defineConfig([
7+
{ files: ["**/*.{js,mjs,cjs}"] },
8+
config,
9+
]);",
910
"configFilename": "eslint.config.mjs",
1011
"devDependencies": [
1112
"eslint@>=9.8.0",

tests/__snapshots__/empty

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
{
2-
"configContent": "
2+
"configContent": "import { defineConfig } from "eslint/config";
33

4-
/** @type {import('eslint').Linter.Config[]} */
5-
export default [
6-
{}
7-
];",
4+
5+
export default defineConfig([
6+
{ files: ["**/*.{js,mjs,cjs}"] },
7+
]);",
88
"configFilename": "eslint.config.js",
99
"devDependencies": [
1010
"eslint",

tests/__snapshots__/problems-commonjs-none-javascript

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
{
2-
"configContent": "import globals from "globals";
3-
import pluginJs from "@eslint/js";
2+
"configContent": "import { defineConfig } from "eslint/config";
3+
import globals from "globals";
4+
import js from "@eslint/js";
45

56

6-
/** @type {import('eslint').Linter.Config[]} */
7-
export default [
8-
{files: ["**/*.js"], languageOptions: {sourceType: "commonjs"}},
9-
{languageOptions: { globals: {...globals.browser, ...globals.node} }},
10-
pluginJs.configs.recommended,
11-
];",
7+
export default defineConfig([
8+
{ files: ["**/*.{js,mjs,cjs}"] },
9+
{ files: ["**/*.js"], languageOptions: { sourceType: "commonjs" } },
10+
{ files: ["**/*.{js,mjs,cjs}"], languageOptions: { globals: {...globals.browser, ...globals.node} } },
11+
{ files: ["**/*.{js,mjs,cjs}"], plugins: { js }, extends: ["js/recommended"] },
12+
]);",
1213
"configFilename": "eslint.config.js",
1314
"devDependencies": [
1415
"eslint",

tests/__snapshots__/problems-commonjs-none-typescript

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
{
2-
"configContent": "import globals from "globals";
3-
import pluginJs from "@eslint/js";
2+
"configContent": "import { defineConfig } from "eslint/config";
3+
import globals from "globals";
4+
import js from "@eslint/js";
45
import tseslint from "typescript-eslint";
56

67

7-
/** @type {import('eslint').Linter.Config[]} */
8-
export default [
9-
{files: ["**/*.{js,mjs,cjs,ts}"]},
10-
{files: ["**/*.js"], languageOptions: {sourceType: "commonjs"}},
11-
{languageOptions: { globals: {...globals.browser, ...globals.node} }},
12-
pluginJs.configs.recommended,
13-
...tseslint.configs.recommended,
14-
];",
8+
export default defineConfig([
9+
{ files: ["**/*.{js,mjs,cjs,ts}"] },
10+
{ files: ["**/*.js"], languageOptions: { sourceType: "commonjs" } },
11+
{ files: ["**/*.{js,mjs,cjs,ts}"], languageOptions: { globals: {...globals.browser, ...globals.node} } },
12+
{ files: ["**/*.{js,mjs,cjs,ts}"], plugins: { js }, extends: ["js/recommended"] },
13+
tseslint.configs.recommended,
14+
]);",
1515
"configFilename": "eslint.config.js",
1616
"devDependencies": [
1717
"eslint",

0 commit comments

Comments
 (0)