diff --git a/lib/configs/flat/base.js b/lib/configs/flat/base.js new file mode 100644 index 000000000..eca4a0949 --- /dev/null +++ b/lib/configs/flat/base.js @@ -0,0 +1,24 @@ +/* + * IMPORTANT! + * This file has been automatically generated, + * in order to update its content execute "npm run update" + */ +const globals = require('globals') +const vueEslintParser = require('vue-eslint-parser') +module.exports = { + languageOptions: { + parser: vueEslintParser, + globals: { + ...globals.browser, + ...globals.es2015 + }, + parserOptions: { + ecmaVersion: 2020, + sourceType: 'module' + } + }, + rules: { + 'vue/comment-directive': 'error', + 'vue/jsx-uses-vars': 'error' + } +} diff --git a/lib/configs/flat/essential.js b/lib/configs/flat/essential.js new file mode 100644 index 000000000..25fc2d50e --- /dev/null +++ b/lib/configs/flat/essential.js @@ -0,0 +1,74 @@ +/* + * IMPORTANT! + * This file has been automatically generated, + * in order to update its content execute "npm run update" + */ +const extendedConfig = require('./base') +module.exports = { + extendedConfig, + rules: { + 'vue/multi-word-component-names': 'error', + 'vue/no-arrow-functions-in-watch': 'error', + 'vue/no-async-in-computed-properties': 'error', + 'vue/no-child-content': 'error', + 'vue/no-computed-properties-in-data': 'error', + 'vue/no-custom-modifiers-on-v-model': 'error', + 'vue/no-dupe-keys': 'error', + 'vue/no-dupe-v-else-if': 'error', + 'vue/no-duplicate-attributes': 'error', + 'vue/no-export-in-script-setup': 'error', + 'vue/no-multiple-template-root': 'error', + 'vue/no-mutating-props': 'error', + 'vue/no-parsing-error': 'error', + 'vue/no-ref-as-operand': 'error', + 'vue/no-reserved-component-names': 'error', + 'vue/no-reserved-keys': 'error', + 'vue/no-reserved-props': [ + 'error', + { + vueVersion: 2 + } + ], + 'vue/no-shared-component-data': 'error', + 'vue/no-side-effects-in-computed-properties': 'error', + 'vue/no-template-key': 'error', + 'vue/no-textarea-mustache': 'error', + 'vue/no-unused-components': 'error', + 'vue/no-unused-vars': 'error', + 'vue/no-use-computed-property-like-method': 'error', + 'vue/no-use-v-if-with-v-for': 'error', + 'vue/no-useless-template-attributes': 'error', + 'vue/no-v-for-template-key': 'error', + 'vue/no-v-model-argument': 'error', + 'vue/no-v-text-v-html-on-component': 'error', + 'vue/require-component-is': 'error', + 'vue/require-prop-type-constructor': 'error', + 'vue/require-render-return': 'error', + 'vue/require-v-for-key': 'error', + 'vue/require-valid-default-prop': 'error', + 'vue/return-in-computed-property': 'error', + 'vue/return-in-emits-validator': 'error', + 'vue/use-v-on-exact': 'error', + 'vue/valid-attribute-name': 'error', + 'vue/valid-define-emits': 'error', + 'vue/valid-define-props': 'error', + 'vue/valid-model-definition': 'error', + 'vue/valid-next-tick': 'error', + 'vue/valid-template-root': 'error', + 'vue/valid-v-bind-sync': 'error', + 'vue/valid-v-bind': 'error', + 'vue/valid-v-cloak': 'error', + 'vue/valid-v-else-if': 'error', + 'vue/valid-v-else': 'error', + 'vue/valid-v-for': 'error', + 'vue/valid-v-html': 'error', + 'vue/valid-v-if': 'error', + 'vue/valid-v-model': 'error', + 'vue/valid-v-on': 'error', + 'vue/valid-v-once': 'error', + 'vue/valid-v-pre': 'error', + 'vue/valid-v-show': 'error', + 'vue/valid-v-slot': 'error', + 'vue/valid-v-text': 'error' + } +} diff --git a/lib/configs/flat/recommended.js b/lib/configs/flat/recommended.js new file mode 100644 index 000000000..282ec0b20 --- /dev/null +++ b/lib/configs/flat/recommended.js @@ -0,0 +1,18 @@ +/* + * IMPORTANT! + * This file has been automatically generated, + * in order to update its content execute "npm run update" + */ +const extendedConfig = require('./strongly-recommended') +module.exports = { + extendedConfig, + rules: { + 'vue/attributes-order': 'warn', + 'vue/component-tags-order': 'warn', + 'vue/no-lone-template': 'warn', + 'vue/no-multiple-slot-args': 'warn', + 'vue/no-v-html': 'warn', + 'vue/order-in-components': 'warn', + 'vue/this-in-template': 'warn' + } +} diff --git a/lib/configs/flat/strongly-recommended.js b/lib/configs/flat/strongly-recommended.js new file mode 100644 index 000000000..2f1044a49 --- /dev/null +++ b/lib/configs/flat/strongly-recommended.js @@ -0,0 +1,34 @@ +/* + * IMPORTANT! + * This file has been automatically generated, + * in order to update its content execute "npm run update" + */ +const extendedConfig = require('./essential') +module.exports = { + extendedConfig, + rules: { + 'vue/attribute-hyphenation': 'warn', + 'vue/component-definition-name-casing': 'warn', + 'vue/first-attribute-linebreak': 'warn', + 'vue/html-closing-bracket-newline': 'warn', + 'vue/html-closing-bracket-spacing': 'warn', + 'vue/html-end-tags': 'warn', + 'vue/html-indent': 'warn', + 'vue/html-quotes': 'warn', + 'vue/html-self-closing': 'warn', + 'vue/max-attributes-per-line': 'warn', + 'vue/multiline-html-element-content-newline': 'warn', + 'vue/mustache-interpolation-spacing': 'warn', + 'vue/no-multi-spaces': 'warn', + 'vue/no-spaces-around-equal-signs-in-attribute': 'warn', + 'vue/no-template-shadow': 'warn', + 'vue/one-component-per-file': 'warn', + 'vue/prop-name-casing': 'warn', + 'vue/require-default-prop': 'warn', + 'vue/require-prop-types': 'warn', + 'vue/singleline-html-element-content-newline': 'warn', + 'vue/v-bind-style': 'warn', + 'vue/v-on-style': 'warn', + 'vue/v-slot-style': 'warn' + } +} diff --git a/lib/configs/flat/vue3-essential.js b/lib/configs/flat/vue3-essential.js new file mode 100644 index 000000000..d34008855 --- /dev/null +++ b/lib/configs/flat/vue3-essential.js @@ -0,0 +1,91 @@ +/* + * IMPORTANT! + * This file has been automatically generated, + * in order to update its content execute "npm run update" + */ +const extendedConfig = require('./base') +module.exports = { + extendedConfig, + rules: { + 'vue/multi-word-component-names': 'error', + 'vue/no-arrow-functions-in-watch': 'error', + 'vue/no-async-in-computed-properties': 'error', + 'vue/no-child-content': 'error', + 'vue/no-computed-properties-in-data': 'error', + 'vue/no-deprecated-data-object-declaration': 'error', + 'vue/no-deprecated-destroyed-lifecycle': 'error', + 'vue/no-deprecated-dollar-listeners-api': 'error', + 'vue/no-deprecated-dollar-scopedslots-api': 'error', + 'vue/no-deprecated-events-api': 'error', + 'vue/no-deprecated-filter': 'error', + 'vue/no-deprecated-functional-template': 'error', + 'vue/no-deprecated-html-element-is': 'error', + 'vue/no-deprecated-inline-template': 'error', + 'vue/no-deprecated-props-default-this': 'error', + 'vue/no-deprecated-router-link-tag-prop': 'error', + 'vue/no-deprecated-scope-attribute': 'error', + 'vue/no-deprecated-slot-attribute': 'error', + 'vue/no-deprecated-slot-scope-attribute': 'error', + 'vue/no-deprecated-v-bind-sync': 'error', + 'vue/no-deprecated-v-is': 'error', + 'vue/no-deprecated-v-on-native-modifier': 'error', + 'vue/no-deprecated-v-on-number-modifiers': 'error', + 'vue/no-deprecated-vue-config-keycodes': 'error', + 'vue/no-dupe-keys': 'error', + 'vue/no-dupe-v-else-if': 'error', + 'vue/no-duplicate-attributes': 'error', + 'vue/no-export-in-script-setup': 'error', + 'vue/no-expose-after-await': 'error', + 'vue/no-lifecycle-after-await': 'error', + 'vue/no-mutating-props': 'error', + 'vue/no-parsing-error': 'error', + 'vue/no-ref-as-operand': 'error', + 'vue/no-reserved-component-names': 'error', + 'vue/no-reserved-keys': 'error', + 'vue/no-reserved-props': 'error', + 'vue/no-shared-component-data': 'error', + 'vue/no-side-effects-in-computed-properties': 'error', + 'vue/no-template-key': 'error', + 'vue/no-textarea-mustache': 'error', + 'vue/no-unused-components': 'error', + 'vue/no-unused-vars': 'error', + 'vue/no-use-computed-property-like-method': 'error', + 'vue/no-use-v-if-with-v-for': 'error', + 'vue/no-useless-template-attributes': 'error', + 'vue/no-v-for-template-key-on-child': 'error', + 'vue/no-v-text-v-html-on-component': 'error', + 'vue/no-watch-after-await': 'error', + 'vue/prefer-import-from-vue': 'error', + 'vue/require-component-is': 'error', + 'vue/require-prop-type-constructor': 'error', + 'vue/require-render-return': 'error', + 'vue/require-slots-as-functions': 'error', + 'vue/require-toggle-inside-transition': 'error', + 'vue/require-v-for-key': 'error', + 'vue/require-valid-default-prop': 'error', + 'vue/return-in-computed-property': 'error', + 'vue/return-in-emits-validator': 'error', + 'vue/use-v-on-exact': 'error', + 'vue/valid-attribute-name': 'error', + 'vue/valid-define-emits': 'error', + 'vue/valid-define-props': 'error', + 'vue/valid-next-tick': 'error', + 'vue/valid-template-root': 'error', + 'vue/valid-v-bind': 'error', + 'vue/valid-v-cloak': 'error', + 'vue/valid-v-else-if': 'error', + 'vue/valid-v-else': 'error', + 'vue/valid-v-for': 'error', + 'vue/valid-v-html': 'error', + 'vue/valid-v-if': 'error', + 'vue/valid-v-is': 'error', + 'vue/valid-v-memo': 'error', + 'vue/valid-v-model': 'error', + 'vue/valid-v-on': 'error', + 'vue/valid-v-once': 'error', + 'vue/valid-v-pre': 'error', + 'vue/valid-v-show': 'error', + 'vue/valid-v-slot': 'error', + 'vue/valid-v-text': 'error' + } +} diff --git a/lib/configs/flat/vue3-recommended.js b/lib/configs/flat/vue3-recommended.js new file mode 100644 index 000000000..30f443bda --- /dev/null +++ b/lib/configs/flat/vue3-recommended.js @@ -0,0 +1,18 @@ +/* + * IMPORTANT! + * This file has been automatically generated, + * in order to update its content execute "npm run update" + */ +const extendedConfig = require('./vue3-strongly-recommended') +module.exports = { + extendedConfig, + rules: { + 'vue/attributes-order': 'warn', + 'vue/component-tags-order': 'warn', + 'vue/no-lone-template': 'warn', + 'vue/no-multiple-slot-args': 'warn', + 'vue/no-v-html': 'warn', + 'vue/order-in-components': 'warn', + 'vue/this-in-template': 'warn' + } +} diff --git a/lib/configs/flat/vue3-strongly-recommended.js b/lib/configs/flat/vue3-strongly-recommended.js new file mode 100644 index 000000000..6a3e4a1f6 --- /dev/null +++ b/lib/configs/flat/vue3-strongly-recommended.js @@ -0,0 +1,42 @@ +/* + * IMPORTANT! + * This file has been automatically generated, + * in order to update its content execute "npm run update" + */ +const extendedConfig = require('./vue3-essential') +module.exports = { + extendedConfig, + rules: { + 'vue/attribute-hyphenation': 'warn', + 'vue/component-definition-name-casing': 'warn', + 'vue/first-attribute-linebreak': 'warn', + 'vue/html-closing-bracket-newline': 'warn', + 'vue/html-closing-bracket-spacing': 'warn', + 'vue/html-end-tags': 'warn', + 'vue/html-indent': 'warn', + 'vue/html-quotes': 'warn', + 'vue/html-self-closing': 'warn', + 'vue/max-attributes-per-line': 'warn', + 'vue/multiline-html-element-content-newline': 'warn', + 'vue/mustache-interpolation-spacing': 'warn', + 'vue/no-multi-spaces': 'warn', + 'vue/no-spaces-around-equal-signs-in-attribute': 'warn', + 'vue/no-template-shadow': 'warn', + 'vue/one-component-per-file': 'warn', + 'vue/prop-name-casing': 'warn', + 'vue/require-default-prop': 'warn', + 'vue/require-explicit-emits': 'warn', + 'vue/require-prop-types': 'warn', + 'vue/singleline-html-element-content-newline': 'warn', + 'vue/v-bind-style': 'warn', + 'vue/v-on-event-hyphenation': [ + 'warn', + 'always', + { + autofix: true + } + ], + 'vue/v-on-style': 'warn', + 'vue/v-slot-style': 'warn' + } +} diff --git a/lib/index.js b/lib/index.js index 99421f248..698623899 100644 --- a/lib/index.js +++ b/lib/index.js @@ -258,7 +258,35 @@ module.exports = { 'strongly-recommended': require('./configs/strongly-recommended'), 'vue3-essential': require('./configs/vue3-essential'), 'vue3-recommended': require('./configs/vue3-recommended'), - 'vue3-strongly-recommended': require('./configs/vue3-strongly-recommended') + 'vue3-strongly-recommended': require('./configs/vue3-strongly-recommended'), + 'flat/base': { + plugins: { vue: module }, + ...require('./configs/flat/base') + }, + 'flat/essential': { + plugins: { vue: module }, + ...require('./configs/flat/essential') + }, + 'flat/recommended': { + plugins: { vue: module }, + ...require('./configs/flat/recommended') + }, + 'flat/strongly-recommended': { + plugins: { vue: module }, + ...require('./configs/flat/strongly-recommended') + }, + 'flat/vue3-essential': { + plugins: { vue: module }, + ...require('./configs/flat/vue3-essential') + }, + 'flat/vue3-recommended': { + plugins: { vue: module }, + ...require('./configs/flat/vue3-recommended') + }, + 'flat/vue3-strongly-recommended': { + plugins: { vue: module }, + ...require('./configs/flat/vue3-strongly-recommended') + } }, processors: { '.vue': require('./processor') diff --git a/tests/lib/configs/configs.js b/tests/lib/configs/configs.js index e995ece4e..64f5b7ea5 100644 --- a/tests/lib/configs/configs.js +++ b/tests/lib/configs/configs.js @@ -5,6 +5,10 @@ const plugin = require('../../../lib/index') describe('configs', () => { for (const name of Object.keys(plugin.configs)) { + if (name.startsWith('flat/')) { + continue + } + const configName = `plugin:vue/${name}` const eslint = new ESLint({ overrideConfig: { diff --git a/tools/lib/configs.js b/tools/lib/configs.js index 031f41e67..ff4efe840 100644 --- a/tools/lib/configs.js +++ b/tools/lib/configs.js @@ -8,8 +8,25 @@ const fs = require('fs') const path = require('path') const ROOT = path.resolve(__dirname, '../../lib/configs') +const FLAT = path.resolve(ROOT, 'flat') -module.exports = fs - .readdirSync(ROOT) - .filter((file) => path.extname(file) === '.js') - .map((file) => path.basename(file, '.js')) +/** + * @param {boolean} flat + * @returns {string[]} + */ +function listConfigs(flat) { + const configDir = flat ? FLAT : ROOT + + return fs + .readdirSync(configDir) + .filter((file) => path.extname(file) === '.js') + .map((file) => { + const prefix = flat ? 'flat/' : '' + return prefix + path.basename(file, '.js') + }) +} + +module.exports = { + root: listConfigs(false), + flat: listConfigs(true) +} diff --git a/tools/update-lib-configs.js b/tools/update-lib-configs.js index b8622e4b0..e02a9d044 100644 --- a/tools/update-lib-configs.js +++ b/tools/update-lib-configs.js @@ -16,6 +16,12 @@ const categories = require('./lib/categories') const errorCategories = new Set(['base', 'essential', 'vue3-essential']) +const autoGeneratedMessage = `/* + * IMPORTANT! + * This file has been automatically generated, + * in order to update its content execute "npm run update" + */` + const extendsCategories = { base: null, essential: 'base', @@ -47,14 +53,29 @@ function formatRules(rules, categoryId) { return JSON.stringify(obj, null, 2) } -function formatCategory(category) { +function formatCategory(category, flat = false) { const extendsCategoryId = extendsCategories[category.categoryId] if (extendsCategoryId == null) { - return `/* - * IMPORTANT! - * This file has been automatically generated, - * in order to update its content execute "npm run update" - */ + return flat + ? `${autoGeneratedMessage} +const globals = require('globals') +const vueEslintParser = require('vue-eslint-parser') +module.exports = { + languageOptions: { + parser: vueEslintParser, + globals: { + ...globals.browser, + ...globals.es2015 + }, + parserOptions: { + ecmaVersion: 2020, + sourceType: 'module' + } + }, + rules: ${formatRules(category.rules, category.categoryId)} +} +` + : `${autoGeneratedMessage} module.exports = { parser: require.resolve('vue-eslint-parser'), parserOptions: { @@ -72,11 +93,15 @@ module.exports = { } ` } - return `/* - * IMPORTANT! - * This file has been automatically generated, - * in order to update its content execute "npm run update" - */ + return flat + ? `${autoGeneratedMessage} +const extendedConfig = require('./${extendsCategoryId}') +module.exports = { + extendedConfig, + rules: ${formatRules(category.rules, category.categoryId)} +} +` + : `${autoGeneratedMessage} module.exports = { extends: require.resolve('./${extendsCategoryId}'), rules: ${formatRules(category.rules, category.categoryId)} @@ -91,6 +116,11 @@ for (const category of categories) { const content = formatCategory(category) fs.writeFileSync(filePath, content) + + const flatFilePath = path.join(ROOT, 'flat', `${category.categoryId}.js`) + const flatContent = formatCategory(category, true) + + fs.writeFileSync(flatFilePath, flatContent) } // Format files. diff --git a/tools/update-lib-index.js b/tools/update-lib-index.js index d12830725..c726417a1 100644 --- a/tools/update-lib-index.js +++ b/tools/update-lib-index.js @@ -32,8 +32,14 @@ module.exports = { .join(',\n')} }, configs: { - ${configs + ${configs.root .map((config) => `'${config}': require('./configs/${config}')`) + .join(',\n')}, + ${configs.flat + .map( + (config) => + `'${config}': { plugins: { vue: module }, ...require('./configs/${config}') }` + ) .join(',\n')} }, processors: {