From 878e5d5c16d7b2121c188094410117a6cc9c1db9 Mon Sep 17 00:00:00 2001 From: Joost Kersjes Date: Thu, 11 Apr 2024 20:34:17 +0200 Subject: [PATCH 1/3] feat: add options to generate a flat config --- index.js | 88 ++++++++++++++++++++++++++++++++++++++++++-------- package.json | 2 ++ pnpm-lock.yaml | 61 ++++++++++++++++++++++++++++++++++ 3 files changed, 138 insertions(+), 13 deletions(-) diff --git a/index.js b/index.js index b976859..1efe9da 100644 --- a/index.js +++ b/index.js @@ -52,9 +52,12 @@ export function deepMerge (target, obj) { // This is also used in `create-vue` export default function createConfig ({ vueVersion = '3.x', // '2.x' | '3.x' (TODO: 2.7 / vue-demi) + configFormat = 'eslintrc', // eslintrc | flat - styleGuide = 'default', // default | airbnb | typescript - hasTypeScript = false, // js | ts + filePatterns = [], // flat format only - e.g. '**/*.vue', '**/*.js', etc. + + styleGuide = 'default', // default | airbnb | standard + hasTypeScript = false, // true | false needsPrettier = false, // true | false additionalConfig = {}, // e.g. Cypress, createAliasSetting for Airbnb, etc. @@ -69,13 +72,18 @@ export default function createConfig ({ addDependency('eslint') addDependency('eslint-plugin-vue') - if (styleGuide !== 'default' || hasTypeScript || needsPrettier) { + if (configFormat === 'flat') { + addDependency('@eslint/eslintrc') + addDependency('@eslint/js') + } else if (styleGuide !== 'default' || hasTypeScript || needsPrettier) { addDependency('@rushstack/eslint-patch') } const language = hasTypeScript ? 'typescript' : 'javascript' - const eslintConfig = { + const flatConfigExtends = [] + const flatConfigImports = [] + const eslintrcConfig = { root: true, extends: [ vueVersion.startsWith('2') @@ -85,49 +93,77 @@ export default function createConfig ({ } const addDependencyAndExtend = (name) => { addDependency(name) - eslintConfig.extends.push(name) + eslintrcConfig.extends.push(name) } switch (`${styleGuide}-${language}`) { case 'default-javascript': - eslintConfig.extends.push('eslint:recommended') + eslintrcConfig.extends.push('eslint:recommended') + flatConfigImports.push(`import js from '@eslint/js'`) + flatConfigExtends.push('js.configs.recommended') break case 'default-typescript': - eslintConfig.extends.push('eslint:recommended') + eslintrcConfig.extends.push('eslint:recommended') + flatConfigImports.push(`import js from '@eslint/js'`) + flatConfigExtends.push('js.configs.recommended') addDependencyAndExtend('@vue/eslint-config-typescript') + flatConfigExtends.push(`...compat.extends('@vue/eslint-config-typescript')`) break case 'airbnb-javascript': case 'standard-javascript': addDependencyAndExtend(`@vue/eslint-config-${styleGuide}`) + flatConfigExtends.push(`...compat.extends('@vue/eslint-config-${styleGuide}')`) break case 'airbnb-typescript': case 'standard-typescript': addDependencyAndExtend(`@vue/eslint-config-${styleGuide}-with-typescript`) + flatConfigExtends.push(`...compat.extends('@vue/eslint-config-${styleGuide}-with-typescript')`) break default: throw new Error(`unexpected combination of styleGuide and language: ${styleGuide}-${language}`) } + flatConfigImports.push(`import pluginVue from 'eslint-plugin-vue'`) + flatConfigExtends.push( + vueVersion.startsWith('2') + ? `...pluginVue.configs['flat/vue2-essential']` + : `...pluginVue.configs['flat/essential']` + ) + deepMerge(pkg.devDependencies, additionalDependencies) - deepMerge(eslintConfig, additionalConfig) + deepMerge(eslintrcConfig, additionalConfig) + + const flatConfigEntry = { + files: filePatterns + } + deepMerge(flatConfigEntry, additionalConfig) if (needsPrettier) { addDependency('prettier') addDependency('@vue/eslint-config-prettier') - eslintConfig.extends.push('@vue/eslint-config-prettier/skip-formatting') + eslintrcConfig.extends.push('@vue/eslint-config-prettier/skip-formatting') + flatConfigExtends.push(`...compat.extends('@vue/eslint-config-prettier/skip-formatting')`) } + const configFilename = configFormat === 'flat' + ? 'eslint.config.js' + : '.eslintrc.cjs' const files = { - '.eslintrc.cjs': '' + [configFilename]: '' } if (styleGuide === 'default') { // Both Airbnb & Standard have already set `env: node` - files['.eslintrc.cjs'] += '/* eslint-env node */\n' + if (configFormat === 'eslintrc') { + files['.eslintrc.cjs'] += '/* eslint-env node */\n' + } // Both Airbnb & Standard have already set `ecmaVersion` // The default in eslint-plugin-vue is 2020, which doesn't support top-level await - eslintConfig.parserOptions = { + eslintrcConfig.parserOptions = { + ecmaVersion: 'latest' + } + flatConfigEntry.languageOptions = { ecmaVersion: 'latest' } } @@ -136,7 +172,33 @@ export default function createConfig ({ files['.eslintrc.cjs'] += "require('@rushstack/eslint-patch/modern-module-resolution')\n\n" } - files['.eslintrc.cjs'] += `module.exports = ${stringifyJS(eslintConfig, styleGuide)}\n` + // eslint.config.js | .eslintrc.cjs + if (configFormat === 'flat') { + files['eslint.config.js'] += "import path from 'node:path'\n" + files['eslint.config.js'] += "import { fileURLToPath } from 'node:url'\n\n" + + flatConfigImports.forEach((pkgImport) => { + files['eslint.config.js'] += `${pkgImport}\n` + }) + files['eslint.config.js'] += '\n' + + // neccesary for compatibility until all packages support flat config + files['eslint.config.js'] += 'const __filename = fileURLToPath(import.meta.url)\n' + files['eslint.config.js'] += 'const __dirname = path.dirname(__filename)\n' + files['eslint.config.js'] += 'const compat = new FlatCompat({\n' + files['eslint.config.js'] += ' baseDirectory: __dirname\n' + files['eslint.config.js'] += '})\n\n' + + files['eslint.config.js'] += 'export default [\n' + flatConfigExtends.forEach((usage) => { + files['eslint.config.js'] += ` ${usage},\n` + }) + + const [, ...keep] = stringifyJS([flatConfigEntry], styleGuide).split('{') + files['eslint.config.js'] += ` {${keep.join('{')}\n` + } else { + files['.eslintrc.cjs'] += `module.exports = ${stringifyJS(eslintrcConfig, styleGuide)}\n` + } // .editorconfig & .prettierrc.json if (editorconfigs[styleGuide]) { diff --git a/package.json b/package.json index d80996b..8d0a1fc 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,8 @@ "kolorist": "^1.8.0" }, "devDependencies": { + "@eslint/eslintrc": "^3.0.2", + "@eslint/js": "^9.0.0", "@rushstack/eslint-patch": "^1.10.1", "@vue/eslint-config-airbnb": "^8.0.0", "@vue/eslint-config-airbnb-with-typescript": "^8.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e3cf1a5..bff37e8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -16,6 +16,12 @@ dependencies: version: 1.8.0 devDependencies: + '@eslint/eslintrc': + specifier: ^3.0.2 + version: 3.0.2 + '@eslint/js': + specifier: ^9.0.0 + version: 9.0.0 '@rushstack/eslint-patch': specifier: ^1.10.1 version: 1.10.1 @@ -112,11 +118,33 @@ packages: - supports-color dev: true + /@eslint/eslintrc@3.0.2: + resolution: {integrity: sha512-wV19ZEGEMAC1eHgrS7UQPqsdEiCIbTKTasEfcXAigzoXICcqZSjBZEHlZwNVvKg6UBCjSlos84XiLqsRJnIcIg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + dependencies: + ajv: 6.12.6 + debug: 4.3.4 + espree: 10.0.1 + globals: 14.0.0 + ignore: 5.2.4 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + dev: true + /@eslint/js@8.57.0: resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true + /@eslint/js@9.0.0: + resolution: {integrity: sha512-RThY/MnKrhubF6+s1JflwUjPEsnCEmYCWwqa/aRISKWNXGZ9epUwft4bUMM35SdKF9xvBrLydAM1RDHd1Z//ZQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + dev: true + /@humanwhocodes/config-array@0.11.14: resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} engines: {node: '>=10.10.0'} @@ -745,12 +773,26 @@ packages: acorn: 8.10.0 dev: true + /acorn-jsx@5.3.2(acorn@8.11.3): + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + acorn: 8.11.3 + dev: true + /acorn@8.10.0: resolution: {integrity: sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==} engines: {node: '>=0.4.0'} hasBin: true dev: true + /acorn@8.11.3: + resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: true + /ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} dependencies: @@ -1931,6 +1973,11 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true + /eslint-visitor-keys@4.0.0: + resolution: {integrity: sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + dev: true + /eslint@8.57.0: resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -1978,6 +2025,15 @@ packages: - supports-color dev: true + /espree@10.0.1: + resolution: {integrity: sha512-MWkrWZbJsL2UwnjxTX3gG8FneachS/Mwg7tdGXce011sJd5b0JG54vat5KHnfSBODZ3Wvzd2WnjxyzsRoVv+ww==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + dependencies: + acorn: 8.11.3 + acorn-jsx: 5.3.2(acorn@8.11.3) + eslint-visitor-keys: 4.0.0 + dev: true + /espree@9.6.1: resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -2216,6 +2272,11 @@ packages: type-fest: 0.20.2 dev: true + /globals@14.0.0: + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} + engines: {node: '>=18'} + dev: true + /globalthis@1.0.3: resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} engines: {node: '>= 0.4'} From 38972836ccc6eb1fba9349811fb4ba87b1fcecf6 Mon Sep 17 00:00:00 2001 From: Joost Kersjes Date: Thu, 11 Apr 2024 22:09:24 +0200 Subject: [PATCH 2/3] feat: support flat config files in bin --- bin/create-eslint-config.js | 73 ++++++++++++++++++++++++------- index.js | 87 +++++++++++++++++++++++++++---------- 2 files changed, 120 insertions(+), 40 deletions(-) diff --git a/bin/create-eslint-config.js b/bin/create-eslint-config.js index 2c858d1..a6d24b9 100644 --- a/bin/create-eslint-config.js +++ b/bin/create-eslint-config.js @@ -42,14 +42,19 @@ const indent = inferIndent(rawPkgJson) const pkg = JSON.parse(rawPkgJson) // 1. check for existing config files -// `.eslintrc.*`, `eslintConfig` in `package.json` +// `.eslintrc.*`, `eslint.config.*` and `eslintConfig` in `package.json` // ask if wanna overwrite? - -// https://eslint.org/docs/latest/user-guide/configuring/configuration-files#configuration-file-formats -// The experimental `eslint.config.js` isn't supported yet -const eslintConfigFormats = ['js', 'cjs', 'yaml', 'yml', 'json'] -for (const fmt of eslintConfigFormats) { - const configFileName = `.eslintrc.${fmt}` +const eslintConfigFormats = [ + '.eslintrc.js', + '.eslintrc.cjs', + '.eslintrc.yaml', + '.eslintrc.yml', + '.eslintrc.json', + 'eslint.config.js', + 'eslint.config.mjs', + 'eslint.config.cjs' +] +for (const configFileName of eslintConfigFormats) { const fullConfigPath = path.resolve(cwd, configFileName) if (existsSync(fullConfigPath)) { const { shouldRemove } = await prompt({ @@ -88,7 +93,39 @@ if (pkg.eslintConfig) { } } -// 2. Check Vue +// 2. Config format +let configFormat +try { + const eslintVersion = requireInCwd('eslint/package.json').version + console.info(dim(`Detected ESLint version: ${eslintVersion}`)) + const [major, minor] = eslintVersion.split('.') + if (parseInt(major) >= 9) { + configFormat = 'flat' + } else if (parseInt(major) === 8 && parseInt(minor) >= 57) { + throw eslintVersion + } else { + configFormat = 'eslintrc' + } +} catch (e) { + const anwsers = await prompt({ + type: 'select', + name: 'configFormat', + message: 'Which configuration file format should be used?', + choices: [ + { + name: 'flat', + message: 'eslint.config.js (a.k.a. Flat Config, the new default)' + }, + { + name: 'eslintrc', + message: `.eslintrc.cjs (deprecated with ESLint v9.0.0)` + }, + ] + }) + configFormat = anwsers.configFormat +} + +// 3. Check Vue // Not detected? Choose from Vue 2 or 3 // TODO: better support for 2.7 and vue-demi let vueVersion @@ -108,7 +145,7 @@ try { vueVersion = anwsers.vueVersion } -// 3. Choose a style guide +// 4. Choose a style guide // - Error Prevention (ESLint Recommended) // - Standard // - Airbnb @@ -132,10 +169,10 @@ const { styleGuide } = await prompt({ ] }) -// 4. Check TypeScript -// 4.1 Allow JS? -// 4.2 Allow JS in Vue? -// 4.3 Allow JSX (TSX, if answered no in 4.1) in Vue? +// 5. Check TypeScript +// 5.1 Allow JS? +// 5.2 Allow JS in Vue? +// 5.3 Allow JSX (TSX, if answered no in 5.1) in Vue? let hasTypeScript = false const additionalConfig = {} try { @@ -200,7 +237,7 @@ if (hasTypeScript && styleGuide !== 'default') { } } -// 5. If Airbnb && !TypeScript +// 6. If Airbnb && !TypeScript // Does your project use any path aliases? // Show [snippet prompts](https://github.com/enquirer/enquirer#snippet-prompt) for the user to input aliases if (styleGuide === 'airbnb' && !hasTypeScript) { @@ -255,7 +292,7 @@ if (styleGuide === 'airbnb' && !hasTypeScript) { } } -// 6. Do you need Prettier to format your codebase? +// 7. Do you need Prettier to format your codebase? const { needsPrettier } = await prompt({ type: 'toggle', disabled: 'No', @@ -266,6 +303,8 @@ const { needsPrettier } = await prompt({ const { pkg: pkgToExtend, files } = createConfig({ vueVersion, + configFormat, + styleGuide, hasTypeScript, needsPrettier, @@ -291,6 +330,8 @@ for (const [name, content] of Object.entries(files)) { writeFileSync(fullPath, content, 'utf-8') } +const configFilename = configFormat === 'flat' ? 'eslint.config.js' : '.eslintrc.cjs' + // Prompt: Run `npm install` or `yarn` or `pnpm install` const userAgent = process.env.npm_config_user_agent ?? '' const packageManager = /pnpm/.test(userAgent) ? 'pnpm' : /yarn/.test(userAgent) ? 'yarn' : 'npm' @@ -300,7 +341,7 @@ const lintCommand = packageManager === 'npm' ? 'npm run lint' : `${packageManage console.info( '\n' + - `${bold(yellow('package.json'))} and ${bold(blue('.eslintrc.cjs'))} have been updated.\n` + + `${bold(yellow('package.json'))} and ${bold(blue(configFilename))} have been updated.\n` + `Now please run ${bold(green(installCommand))} to re-install the dependencies.\n` + `Then you can run ${bold(green(lintCommand))} to lint your files.` ) diff --git a/index.js b/index.js index 1efe9da..c46717b 100644 --- a/index.js +++ b/index.js @@ -8,7 +8,7 @@ import versionMap from './versionMap.cjs' const CREATE_ALIAS_SETTING_PLACEHOLDER = 'CREATE_ALIAS_SETTING_PLACEHOLDER' export { CREATE_ALIAS_SETTING_PLACEHOLDER } -function stringifyJS (value, styleGuide) { +function stringifyJS (value, styleGuide, configFormat) { // eslint-disable-next-line no-shadow const result = stringify(value, (val, indent, stringify, key) => { if (key === 'CREATE_ALIAS_SETTING_PLACEHOLDER') { @@ -18,6 +18,10 @@ function stringifyJS (value, styleGuide) { return stringify(val) }, 2) + if (configFormat === 'flat') { + return result.replace('CREATE_ALIAS_SETTING_PLACEHOLDER: ', '...createAliasSetting') + } + return result.replace( 'CREATE_ALIAS_SETTING_PLACEHOLDER: ', `...require('@vue/eslint-config-${styleGuide}/createAliasSetting')` @@ -72,17 +76,15 @@ export default function createConfig ({ addDependency('eslint') addDependency('eslint-plugin-vue') - if (configFormat === 'flat') { - addDependency('@eslint/eslintrc') - addDependency('@eslint/js') - } else if (styleGuide !== 'default' || hasTypeScript || needsPrettier) { - addDependency('@rushstack/eslint-patch') + if ( + configFormat === "eslintrc" && + (styleGuide !== "default" || hasTypeScript || needsPrettier) + ) { + addDependency("@rushstack/eslint-patch"); } const language = hasTypeScript ? 'typescript' : 'javascript' - const flatConfigExtends = [] - const flatConfigImports = [] const eslintrcConfig = { root: true, extends: [ @@ -96,6 +98,20 @@ export default function createConfig ({ eslintrcConfig.extends.push(name) } + let needsFlatCompat = false + const flatConfigExtends = [] + const flatConfigImports = [] + flatConfigImports.push(`import pluginVue from 'eslint-plugin-vue'`) + flatConfigExtends.push( + vueVersion.startsWith('2') + ? `...pluginVue.configs['flat/vue2-essential']` + : `...pluginVue.configs['flat/essential']` + ) + + if (configFormat === 'flat' && styleGuide === 'default') { + addDependency('@eslint/js') + } + switch (`${styleGuide}-${language}`) { case 'default-javascript': eslintrcConfig.extends.push('eslint:recommended') @@ -107,41 +123,53 @@ export default function createConfig ({ flatConfigImports.push(`import js from '@eslint/js'`) flatConfigExtends.push('js.configs.recommended') addDependencyAndExtend('@vue/eslint-config-typescript') + needsFlatCompat = true flatConfigExtends.push(`...compat.extends('@vue/eslint-config-typescript')`) break case 'airbnb-javascript': case 'standard-javascript': addDependencyAndExtend(`@vue/eslint-config-${styleGuide}`) + needsFlatCompat = true flatConfigExtends.push(`...compat.extends('@vue/eslint-config-${styleGuide}')`) break case 'airbnb-typescript': case 'standard-typescript': addDependencyAndExtend(`@vue/eslint-config-${styleGuide}-with-typescript`) + needsFlatCompat = true flatConfigExtends.push(`...compat.extends('@vue/eslint-config-${styleGuide}-with-typescript')`) break default: throw new Error(`unexpected combination of styleGuide and language: ${styleGuide}-${language}`) } - flatConfigImports.push(`import pluginVue from 'eslint-plugin-vue'`) - flatConfigExtends.push( - vueVersion.startsWith('2') - ? `...pluginVue.configs['flat/vue2-essential']` - : `...pluginVue.configs['flat/essential']` - ) - deepMerge(pkg.devDependencies, additionalDependencies) deepMerge(eslintrcConfig, additionalConfig) + if (additionalConfig?.extends) { + needsFlatCompat = true + additionalConfig.extends.forEach((pkgName) => { + flatConfigExtends.push(`...compat.extends('${pkgName}')`) + }) + } + const flatConfigEntry = { files: filePatterns } - deepMerge(flatConfigEntry, additionalConfig) + if (additionalConfig?.settings?.[CREATE_ALIAS_SETTING_PLACEHOLDER]) { + flatConfigImports.push( + `import createAliasSetting from '@vue/eslint-config-${styleGuide}/createAliasSetting'` + ) + flatConfigEntry.settings = { + [CREATE_ALIAS_SETTING_PLACEHOLDER]: + additionalConfig.settings[CREATE_ALIAS_SETTING_PLACEHOLDER] + } + } if (needsPrettier) { addDependency('prettier') addDependency('@vue/eslint-config-prettier') eslintrcConfig.extends.push('@vue/eslint-config-prettier/skip-formatting') + needsFlatCompat = true flatConfigExtends.push(`...compat.extends('@vue/eslint-config-prettier/skip-formatting')`) } @@ -174,27 +202,38 @@ export default function createConfig ({ // eslint.config.js | .eslintrc.cjs if (configFormat === 'flat') { - files['eslint.config.js'] += "import path from 'node:path'\n" - files['eslint.config.js'] += "import { fileURLToPath } from 'node:url'\n\n" + if (needsFlatCompat) { + files['eslint.config.js'] += "import path from 'node:path'\n" + files['eslint.config.js'] += "import { fileURLToPath } from 'node:url'\n\n" + + addDependency('@eslint/eslintrc') + files['eslint.config.js'] += "import { FlatCompat } from '@eslint/eslintrc'\n" + } + // imports flatConfigImports.forEach((pkgImport) => { files['eslint.config.js'] += `${pkgImport}\n` }) files['eslint.config.js'] += '\n' // neccesary for compatibility until all packages support flat config - files['eslint.config.js'] += 'const __filename = fileURLToPath(import.meta.url)\n' - files['eslint.config.js'] += 'const __dirname = path.dirname(__filename)\n' - files['eslint.config.js'] += 'const compat = new FlatCompat({\n' - files['eslint.config.js'] += ' baseDirectory: __dirname\n' - files['eslint.config.js'] += '})\n\n' + if (needsFlatCompat) { + files['eslint.config.js'] += 'const __filename = fileURLToPath(import.meta.url)\n' + files['eslint.config.js'] += 'const __dirname = path.dirname(__filename)\n' + files['eslint.config.js'] += 'const compat = new FlatCompat({\n' + files['eslint.config.js'] += ' baseDirectory: __dirname' + if (pkg.devDependencies['@vue/eslint-config-typescript']) { + files['eslint.config.js'] += ',\n recommendedConfig: js.configs.recommended' + } + files['eslint.config.js'] += '\n})\n\n' + } files['eslint.config.js'] += 'export default [\n' flatConfigExtends.forEach((usage) => { files['eslint.config.js'] += ` ${usage},\n` }) - const [, ...keep] = stringifyJS([flatConfigEntry], styleGuide).split('{') + const [, ...keep] = stringifyJS([flatConfigEntry], styleGuide, "flat").split('{') files['eslint.config.js'] += ` {${keep.join('{')}\n` } else { files['.eslintrc.cjs'] += `module.exports = ${stringifyJS(eslintrcConfig, styleGuide)}\n` From af60961c2feb56bf9a8c68e34801a4c40ccd224f Mon Sep 17 00:00:00 2001 From: Joost Kersjes Date: Fri, 12 Apr 2024 19:40:39 +0200 Subject: [PATCH 3/3] feat: add file patterns to flat config --- index.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/index.js b/index.js index c46717b..79a0066 100644 --- a/index.js +++ b/index.js @@ -58,8 +58,6 @@ export default function createConfig ({ vueVersion = '3.x', // '2.x' | '3.x' (TODO: 2.7 / vue-demi) configFormat = 'eslintrc', // eslintrc | flat - filePatterns = [], // flat format only - e.g. '**/*.vue', '**/*.js', etc. - styleGuide = 'default', // default | airbnb | standard hasTypeScript = false, // true | false needsPrettier = false, // true | false @@ -153,7 +151,9 @@ export default function createConfig ({ } const flatConfigEntry = { - files: filePatterns + files: language === 'javascript' + ? ['**/*.vue','**/*.js','**/*.jsx','**/*.cjs','**/*.mjs'] + : ['**/*.vue','**/*.js','**/*.jsx','**/*.cjs','**/*.mjs','**/*.ts','**/*.tsx','**/*.cts','**/*.mts'] } if (additionalConfig?.settings?.[CREATE_ALIAS_SETTING_PLACEHOLDER]) { flatConfigImports.push(