From 426f5afe4af8ca0a854616a9918473c5cff73cf2 Mon Sep 17 00:00:00 2001 From: ItMaga Date: Sun, 30 Jun 2024 22:04:48 +0300 Subject: [PATCH 01/11] Add `vue/require-default-export` rule --- docs/rules/index.md | 1 + docs/rules/object-curly-newline.md | 2 +- docs/rules/object-property-newline.md | 2 +- docs/rules/require-default-export.md | 54 +++++++++ lib/configs/flat/vue2-essential.js | 1 + lib/configs/flat/vue3-essential.js | 1 + lib/configs/vue2-essential.js | 1 + lib/configs/vue3-essential.js | 1 + lib/index.js | 1 + lib/rules/require-default-export.js | 47 ++++++++ tests/lib/rules/require-default-export.js | 136 ++++++++++++++++++++++ 11 files changed, 245 insertions(+), 2 deletions(-) create mode 100644 docs/rules/require-default-export.md create mode 100644 lib/rules/require-default-export.js create mode 100644 tests/lib/rules/require-default-export.js diff --git a/docs/rules/index.md b/docs/rules/index.md index e718603f8..bb3fd0a16 100644 --- a/docs/rules/index.md +++ b/docs/rules/index.md @@ -95,6 +95,7 @@ Rules in this category are enabled for all presets provided by eslint-plugin-vue | [vue/no-watch-after-await](./no-watch-after-await.md) | disallow asynchronously registered `watch` | | :three::hammer: | | [vue/prefer-import-from-vue](./prefer-import-from-vue.md) | enforce import from 'vue' instead of import from '@vue/*' | :wrench: | :three::hammer: | | [vue/require-component-is](./require-component-is.md) | require `v-bind:is` of `` elements | | :three::two::warning: | +| [vue/require-default-export](./require-default-export.md) | require default export | | :three::two::warning: | | [vue/require-prop-type-constructor](./require-prop-type-constructor.md) | require prop type to be a constructor | :wrench: | :three::two::hammer: | | [vue/require-render-return](./require-render-return.md) | enforce render function to always return value | | :three::two::warning: | | [vue/require-slots-as-functions](./require-slots-as-functions.md) | enforce properties of `$slots` to be used as a function | | :three::warning: | diff --git a/docs/rules/object-curly-newline.md b/docs/rules/object-curly-newline.md index c4743c261..f0b0bf677 100644 --- a/docs/rules/object-curly-newline.md +++ b/docs/rules/object-curly-newline.md @@ -36,4 +36,4 @@ This rule was introduced in eslint-plugin-vue v7.0.0 - [Rule source](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/object-curly-newline.js) - [Test source](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/object-curly-newline.js) -Taken with ❤️ [from ESLint Stylistic](https://eslint.style/rules/js/object-curly-newline) +Taken with ❤️ [from ESLint Stylistic](https://eslint.style/rules/ts/object-curly-newline) diff --git a/docs/rules/object-property-newline.md b/docs/rules/object-property-newline.md index c6e315c08..bfba0c0a2 100644 --- a/docs/rules/object-property-newline.md +++ b/docs/rules/object-property-newline.md @@ -36,4 +36,4 @@ This rule was introduced in eslint-plugin-vue v7.0.0 - [Rule source](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/object-property-newline.js) - [Test source](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/object-property-newline.js) -Taken with ❤️ [from ESLint Stylistic](https://eslint.style/rules/js/object-property-newline) +Taken with ❤️ [from ESLint Stylistic](https://eslint.style/rules/ts/object-property-newline) diff --git a/docs/rules/require-default-export.md b/docs/rules/require-default-export.md new file mode 100644 index 000000000..7324d10ba --- /dev/null +++ b/docs/rules/require-default-export.md @@ -0,0 +1,54 @@ +--- +pageClass: rule-details +sidebarDepth: 0 +title: vue/require-default-export +description: require default export +--- + +# vue/require-default-export + +> require default export + +- :exclamation: _**This rule has not been released yet.**_ +- :gear: This rule is included in all of `"plugin:vue/vue3-essential"`, `*.configs["flat/essential"]`, `"plugin:vue/essential"`, `*.configs["flat/vue2-essential"]`, `"plugin:vue/vue3-strongly-recommended"`, `*.configs["flat/strongly-recommended"]`, `"plugin:vue/strongly-recommended"`, `*.configs["flat/vue2-strongly-recommended"]`, `"plugin:vue/vue3-recommended"`, `*.configs["flat/recommended"]`, `"plugin:vue/recommended"` and `*.configs["flat/vue2-recommended"]`. + +## :book: Rule Details + +This rule reports when a Vue component does not have a default export, if the component is not defined as ` +``` + + + + + +```vue + + +``` + + + +## :wrench: Options + +Nothing. + +## :mag: Implementation + +- [Rule source](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/require-default-export.js) +- [Test source](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/require-default-export.js) diff --git a/lib/configs/flat/vue2-essential.js b/lib/configs/flat/vue2-essential.js index 1de89dbc8..06b6b4634 100644 --- a/lib/configs/flat/vue2-essential.js +++ b/lib/configs/flat/vue2-essential.js @@ -46,6 +46,7 @@ module.exports = [ 'vue/no-v-model-argument': 'error', 'vue/no-v-text-v-html-on-component': 'error', 'vue/require-component-is': 'error', + 'vue/require-default-export': 'error', 'vue/require-prop-type-constructor': 'error', 'vue/require-render-return': 'error', 'vue/require-v-for-key': 'error', diff --git a/lib/configs/flat/vue3-essential.js b/lib/configs/flat/vue3-essential.js index 595af5f1d..9bcec98b5 100644 --- a/lib/configs/flat/vue3-essential.js +++ b/lib/configs/flat/vue3-essential.js @@ -61,6 +61,7 @@ module.exports = [ 'vue/no-watch-after-await': 'error', 'vue/prefer-import-from-vue': 'error', 'vue/require-component-is': 'error', + 'vue/require-default-export': 'error', 'vue/require-prop-type-constructor': 'error', 'vue/require-render-return': 'error', 'vue/require-slots-as-functions': 'error', diff --git a/lib/configs/vue2-essential.js b/lib/configs/vue2-essential.js index e2c66ceba..1a8ea3429 100644 --- a/lib/configs/vue2-essential.js +++ b/lib/configs/vue2-essential.js @@ -41,6 +41,7 @@ module.exports = { 'vue/no-v-model-argument': 'error', 'vue/no-v-text-v-html-on-component': 'error', 'vue/require-component-is': 'error', + 'vue/require-default-export': 'error', 'vue/require-prop-type-constructor': 'error', 'vue/require-render-return': 'error', 'vue/require-v-for-key': 'error', diff --git a/lib/configs/vue3-essential.js b/lib/configs/vue3-essential.js index f71508f75..47b3a8113 100644 --- a/lib/configs/vue3-essential.js +++ b/lib/configs/vue3-essential.js @@ -56,6 +56,7 @@ module.exports = { 'vue/no-watch-after-await': 'error', 'vue/prefer-import-from-vue': 'error', 'vue/require-component-is': 'error', + 'vue/require-default-export': 'error', 'vue/require-prop-type-constructor': 'error', 'vue/require-render-return': 'error', 'vue/require-slots-as-functions': 'error', diff --git a/lib/index.js b/lib/index.js index 956eeaa4b..f5b0986a8 100644 --- a/lib/index.js +++ b/lib/index.js @@ -208,6 +208,7 @@ const plugin = { 'prop-name-casing': require('./rules/prop-name-casing'), 'quote-props': require('./rules/quote-props'), 'require-component-is': require('./rules/require-component-is'), + 'require-default-export': require('./rules/require-default-export'), 'require-default-prop': require('./rules/require-default-prop'), 'require-direct-export': require('./rules/require-direct-export'), 'require-emit-validator': require('./rules/require-emit-validator'), diff --git a/lib/rules/require-default-export.js b/lib/rules/require-default-export.js new file mode 100644 index 000000000..50f0a1e25 --- /dev/null +++ b/lib/rules/require-default-export.js @@ -0,0 +1,47 @@ +/** + * @author ItMaga + * See LICENSE file in root directory for full license. + */ +'use strict' + +const utils = require('../utils') + +module.exports = { + meta: { + type: 'problem', + docs: { + description: 'require default export', + categories: ['vue3-essential', 'vue2-essential'], + url: 'https://eslint.vuejs.org/rules/require-default-export.html' + }, + fixable: null, + schema: [], + messages: { + missing: 'Missing default export.' + } + }, + /** @param {RuleContext} context */ + create(context) { + if (utils.isScriptSetup(context)) { + return {} + } + + return { + /** + * @param {Program} node + */ + 'Program:exit'(node) { + const hasDefaultExport = node.body.some( + (item) => item.type === 'ExportDefaultDeclaration' + ) + + if (!hasDefaultExport) { + context.report({ + loc: { line: 1, column: 0 }, + messageId: 'missing' + }) + } + } + } + } +} diff --git a/tests/lib/rules/require-default-export.js b/tests/lib/rules/require-default-export.js new file mode 100644 index 000000000..2e2c2b3d8 --- /dev/null +++ b/tests/lib/rules/require-default-export.js @@ -0,0 +1,136 @@ +/** + * @author ItMaga + * See LICENSE file in root directory for full license. + */ +'use strict' + +const RuleTester = require('../../eslint-compat').RuleTester +const rule = require('../../../lib/rules/require-default-export') + +const tester = new RuleTester({ + languageOptions: { + parser: require('vue-eslint-parser'), + ecmaVersion: 2020, + sourceType: 'module' + } +}) + +tester.run('require-default-export', rule, { + valid: [ + { + filename: 'test.vue', + code: ` + + ` + }, + { + filename: 'test.vue', + code: ` + + ` + }, + { + filename: 'test.vue', + code: ` + + ` + }, + { + filename: 'test.vue', + code: ` + + ` + } + ], + invalid: [ + { + filename: 'test.vue', + code: ` + + `, + errors: [ + { + messageId: 'missing', + line: 1 + } + ] + }, + { + filename: 'test.vue', + code: ` + + `, + errors: [ + { + messageId: 'missing', + line: 1 + } + ] + }, + { + filename: 'test.vue', + code: ` + + `, + errors: [ + { + messageId: 'missing', + line: 1 + } + ] + }, + { + filename: 'test.vue', + code: ` + + `, + errors: [ + { + messageId: 'missing', + line: 1 + } + ] + }, + { + filename: 'test.vue', + code: ` + + `, + errors: [ + { + messageId: 'missing', + line: 1 + } + ] + } + ] +}) From 2daebd6ed0d6a675856219688e952e6981ccec9e Mon Sep 17 00:00:00 2001 From: ItMaga Date: Sun, 30 Jun 2024 23:29:23 +0300 Subject: [PATCH 02/11] fix: without script and jsx --- lib/rules/require-default-export.js | 23 +++++++++++++++++------ tests/lib/rules/require-default-export.js | 6 ++++++ 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/lib/rules/require-default-export.js b/lib/rules/require-default-export.js index 50f0a1e25..163bb6990 100644 --- a/lib/rules/require-default-export.js +++ b/lib/rules/require-default-export.js @@ -22,20 +22,31 @@ module.exports = { }, /** @param {RuleContext} context */ create(context) { - if (utils.isScriptSetup(context)) { + const sourceCode = context.getSourceCode() + const documentFragment = sourceCode.parserServices.getDocumentFragment?.() + + const hasScript = + documentFragment && + documentFragment.children.some( + (e) => utils.isVElement(e) && e.name === 'script' + ) + + if (utils.isScriptSetup(context) || !hasScript) { return {} } + let hasDefaultExport = false + return { + 'Program > ExportDefaultDeclaration'() { + hasDefaultExport = true + }, + /** * @param {Program} node */ 'Program:exit'(node) { - const hasDefaultExport = node.body.some( - (item) => item.type === 'ExportDefaultDeclaration' - ) - - if (!hasDefaultExport) { + if (!hasDefaultExport && node.body.length > 0) { context.report({ loc: { line: 1, column: 0 }, messageId: 'missing' diff --git a/tests/lib/rules/require-default-export.js b/tests/lib/rules/require-default-export.js index 2e2c2b3d8..d268a19ac 100644 --- a/tests/lib/rules/require-default-export.js +++ b/tests/lib/rules/require-default-export.js @@ -17,6 +17,12 @@ const tester = new RuleTester({ tester.run('require-default-export', rule, { valid: [ + { + filename: 'test.vue', + code: ` + + ` + }, { filename: 'test.vue', code: ` From 3f5f4b402cda3ebf57a4c43f8b5756359a913a87 Mon Sep 17 00:00:00 2001 From: ItMaga Date: Sat, 6 Jul 2024 18:40:46 +0300 Subject: [PATCH 03/11] docs: add related rules and revert non-relevant changes --- docs/rules/object-curly-newline.md | 2 +- docs/rules/object-property-newline.md | 2 +- docs/rules/require-default-export.md | 9 ++++++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/docs/rules/object-curly-newline.md b/docs/rules/object-curly-newline.md index f0b0bf677..c4743c261 100644 --- a/docs/rules/object-curly-newline.md +++ b/docs/rules/object-curly-newline.md @@ -36,4 +36,4 @@ This rule was introduced in eslint-plugin-vue v7.0.0 - [Rule source](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/object-curly-newline.js) - [Test source](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/object-curly-newline.js) -Taken with ❤️ [from ESLint Stylistic](https://eslint.style/rules/ts/object-curly-newline) +Taken with ❤️ [from ESLint Stylistic](https://eslint.style/rules/js/object-curly-newline) diff --git a/docs/rules/object-property-newline.md b/docs/rules/object-property-newline.md index bfba0c0a2..c6e315c08 100644 --- a/docs/rules/object-property-newline.md +++ b/docs/rules/object-property-newline.md @@ -36,4 +36,4 @@ This rule was introduced in eslint-plugin-vue v7.0.0 - [Rule source](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/object-property-newline.js) - [Test source](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/object-property-newline.js) -Taken with ❤️ [from ESLint Stylistic](https://eslint.style/rules/ts/object-property-newline) +Taken with ❤️ [from ESLint Stylistic](https://eslint.style/rules/js/object-property-newline) diff --git a/docs/rules/require-default-export.md b/docs/rules/require-default-export.md index 7324d10ba..1760c25fa 100644 --- a/docs/rules/require-default-export.md +++ b/docs/rules/require-default-export.md @@ -2,15 +2,14 @@ pageClass: rule-details sidebarDepth: 0 title: vue/require-default-export -description: require default export +description: require components to be the default export --- # vue/require-default-export -> require default export +> require components to be the default export - :exclamation: _**This rule has not been released yet.**_ -- :gear: This rule is included in all of `"plugin:vue/vue3-essential"`, `*.configs["flat/essential"]`, `"plugin:vue/essential"`, `*.configs["flat/vue2-essential"]`, `"plugin:vue/vue3-strongly-recommended"`, `*.configs["flat/strongly-recommended"]`, `"plugin:vue/strongly-recommended"`, `*.configs["flat/vue2-strongly-recommended"]`, `"plugin:vue/vue3-recommended"`, `*.configs["flat/recommended"]`, `"plugin:vue/recommended"` and `*.configs["flat/vue2-recommended"]`. ## :book: Rule Details @@ -48,6 +47,10 @@ export default { Nothing. +## :couple: Related Rules + +- [vue/one-component-per-file](./one-component-per-file.md) + ## :mag: Implementation - [Rule source](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/require-default-export.js) From dd353c2599a7ea7bc20de04e64f8a76cfef6c14d Mon Sep 17 00:00:00 2001 From: ItMaga Date: Sat, 6 Jul 2024 18:41:18 +0300 Subject: [PATCH 04/11] feat: revert categories and update description --- docs/rules/index.md | 2 +- lib/configs/flat/vue2-essential.js | 1 - lib/configs/flat/vue3-essential.js | 1 - lib/configs/vue2-essential.js | 1 - lib/configs/vue3-essential.js | 1 - lib/rules/require-default-export.js | 4 ++-- 6 files changed, 3 insertions(+), 7 deletions(-) diff --git a/docs/rules/index.md b/docs/rules/index.md index bb3fd0a16..64bd7b81d 100644 --- a/docs/rules/index.md +++ b/docs/rules/index.md @@ -95,7 +95,6 @@ Rules in this category are enabled for all presets provided by eslint-plugin-vue | [vue/no-watch-after-await](./no-watch-after-await.md) | disallow asynchronously registered `watch` | | :three::hammer: | | [vue/prefer-import-from-vue](./prefer-import-from-vue.md) | enforce import from 'vue' instead of import from '@vue/*' | :wrench: | :three::hammer: | | [vue/require-component-is](./require-component-is.md) | require `v-bind:is` of `` elements | | :three::two::warning: | -| [vue/require-default-export](./require-default-export.md) | require default export | | :three::two::warning: | | [vue/require-prop-type-constructor](./require-prop-type-constructor.md) | require prop type to be a constructor | :wrench: | :three::two::hammer: | | [vue/require-render-return](./require-render-return.md) | enforce render function to always return value | | :three::two::warning: | | [vue/require-slots-as-functions](./require-slots-as-functions.md) | enforce properties of `$slots` to be used as a function | | :three::warning: | @@ -268,6 +267,7 @@ For example: | [vue/prefer-prop-type-boolean-first](./prefer-prop-type-boolean-first.md) | enforce `Boolean` comes first in component prop types | :bulb: | :warning: | | [vue/prefer-separate-static-class](./prefer-separate-static-class.md) | require static class names in template to be in a separate `class` attribute | :wrench: | :hammer: | | [vue/prefer-true-attribute-shorthand](./prefer-true-attribute-shorthand.md) | require shorthand form attribute when `v-bind` value is `true` | :bulb: | :hammer: | +| [vue/require-default-export](./require-default-export.md) | require components to be the default export | | :warning: | | [vue/require-direct-export](./require-direct-export.md) | require the component to be directly exported | | :hammer: | | [vue/require-emit-validator](./require-emit-validator.md) | require type definitions in emits | :bulb: | :hammer: | | [vue/require-explicit-slots](./require-explicit-slots.md) | require slots to be explicitly defined | | :warning: | diff --git a/lib/configs/flat/vue2-essential.js b/lib/configs/flat/vue2-essential.js index 06b6b4634..1de89dbc8 100644 --- a/lib/configs/flat/vue2-essential.js +++ b/lib/configs/flat/vue2-essential.js @@ -46,7 +46,6 @@ module.exports = [ 'vue/no-v-model-argument': 'error', 'vue/no-v-text-v-html-on-component': 'error', 'vue/require-component-is': 'error', - 'vue/require-default-export': 'error', 'vue/require-prop-type-constructor': 'error', 'vue/require-render-return': 'error', 'vue/require-v-for-key': 'error', diff --git a/lib/configs/flat/vue3-essential.js b/lib/configs/flat/vue3-essential.js index 9bcec98b5..595af5f1d 100644 --- a/lib/configs/flat/vue3-essential.js +++ b/lib/configs/flat/vue3-essential.js @@ -61,7 +61,6 @@ module.exports = [ 'vue/no-watch-after-await': 'error', 'vue/prefer-import-from-vue': 'error', 'vue/require-component-is': 'error', - 'vue/require-default-export': 'error', 'vue/require-prop-type-constructor': 'error', 'vue/require-render-return': 'error', 'vue/require-slots-as-functions': 'error', diff --git a/lib/configs/vue2-essential.js b/lib/configs/vue2-essential.js index 1a8ea3429..e2c66ceba 100644 --- a/lib/configs/vue2-essential.js +++ b/lib/configs/vue2-essential.js @@ -41,7 +41,6 @@ module.exports = { 'vue/no-v-model-argument': 'error', 'vue/no-v-text-v-html-on-component': 'error', 'vue/require-component-is': 'error', - 'vue/require-default-export': 'error', 'vue/require-prop-type-constructor': 'error', 'vue/require-render-return': 'error', 'vue/require-v-for-key': 'error', diff --git a/lib/configs/vue3-essential.js b/lib/configs/vue3-essential.js index 47b3a8113..f71508f75 100644 --- a/lib/configs/vue3-essential.js +++ b/lib/configs/vue3-essential.js @@ -56,7 +56,6 @@ module.exports = { 'vue/no-watch-after-await': 'error', 'vue/prefer-import-from-vue': 'error', 'vue/require-component-is': 'error', - 'vue/require-default-export': 'error', 'vue/require-prop-type-constructor': 'error', 'vue/require-render-return': 'error', 'vue/require-slots-as-functions': 'error', diff --git a/lib/rules/require-default-export.js b/lib/rules/require-default-export.js index 163bb6990..24d2fc433 100644 --- a/lib/rules/require-default-export.js +++ b/lib/rules/require-default-export.js @@ -10,8 +10,8 @@ module.exports = { meta: { type: 'problem', docs: { - description: 'require default export', - categories: ['vue3-essential', 'vue2-essential'], + description: 'require components to be the default export', + categories: undefined, url: 'https://eslint.vuejs.org/rules/require-default-export.html' }, fixable: null, From 77f112642480065555d7f37bc732320e18a54feb Mon Sep 17 00:00:00 2001 From: ItMaga Date: Sat, 6 Jul 2024 18:41:34 +0300 Subject: [PATCH 05/11] feat: add test suites --- tests/lib/rules/require-default-export.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/lib/rules/require-default-export.js b/tests/lib/rules/require-default-export.js index d268a19ac..088ad09ea 100644 --- a/tests/lib/rules/require-default-export.js +++ b/tests/lib/rules/require-default-export.js @@ -60,6 +60,20 @@ tester.run('require-default-export', rule, { export default defineComponent({}); ` + }, + { + filename: 'test.js', + code: ` + const foo = 'foo'; + export const bar = 'bar'; + ` + }, + { + filename: 'test.js', + code: ` + import {defineComponent} from 'vue'; + defineComponent({}); + ` } ], invalid: [ From 7f986443f1b9258bc9d19c0c49f51db89ed6e841 Mon Sep 17 00:00:00 2001 From: ItMaga Date: Sat, 6 Jul 2024 18:51:07 +0300 Subject: [PATCH 06/11] refactor: improve error message --- lib/rules/require-default-export.js | 4 ++-- tests/lib/rules/require-default-export.js | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/rules/require-default-export.js b/lib/rules/require-default-export.js index 24d2fc433..4053f16bf 100644 --- a/lib/rules/require-default-export.js +++ b/lib/rules/require-default-export.js @@ -17,7 +17,7 @@ module.exports = { fixable: null, schema: [], messages: { - missing: 'Missing default export.' + mustDefaultExport: 'The component must be the default export.' } }, /** @param {RuleContext} context */ @@ -49,7 +49,7 @@ module.exports = { if (!hasDefaultExport && node.body.length > 0) { context.report({ loc: { line: 1, column: 0 }, - messageId: 'missing' + messageId: 'mustDefaultExport' }) } } diff --git a/tests/lib/rules/require-default-export.js b/tests/lib/rules/require-default-export.js index 088ad09ea..438f057ee 100644 --- a/tests/lib/rules/require-default-export.js +++ b/tests/lib/rules/require-default-export.js @@ -86,7 +86,7 @@ tester.run('require-default-export', rule, { `, errors: [ { - messageId: 'missing', + messageId: 'mustDefaultExport', line: 1 } ] @@ -100,7 +100,7 @@ tester.run('require-default-export', rule, { `, errors: [ { - messageId: 'missing', + messageId: 'mustDefaultExport', line: 1 } ] @@ -116,7 +116,7 @@ tester.run('require-default-export', rule, { `, errors: [ { - messageId: 'missing', + messageId: 'mustDefaultExport', line: 1 } ] @@ -131,7 +131,7 @@ tester.run('require-default-export', rule, { `, errors: [ { - messageId: 'missing', + messageId: 'mustDefaultExport', line: 1 } ] @@ -147,7 +147,7 @@ tester.run('require-default-export', rule, { `, errors: [ { - messageId: 'missing', + messageId: 'mustDefaultExport', line: 1 } ] From 73e00c8e51cd32e384282933ec73d28c14ae3876 Mon Sep 17 00:00:00 2001 From: Flo Edelmann Date: Mon, 8 Jul 2024 09:23:44 +0200 Subject: [PATCH 07/11] Discard changes to docs/rules/object-curly-newline.md --- docs/rules/object-curly-newline.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/rules/object-curly-newline.md b/docs/rules/object-curly-newline.md index c4743c261..f0b0bf677 100644 --- a/docs/rules/object-curly-newline.md +++ b/docs/rules/object-curly-newline.md @@ -36,4 +36,4 @@ This rule was introduced in eslint-plugin-vue v7.0.0 - [Rule source](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/object-curly-newline.js) - [Test source](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/object-curly-newline.js) -Taken with ❤️ [from ESLint Stylistic](https://eslint.style/rules/js/object-curly-newline) +Taken with ❤️ [from ESLint Stylistic](https://eslint.style/rules/ts/object-curly-newline) From b42646ab745bc587dc870a9ca747bf00ac28a5a3 Mon Sep 17 00:00:00 2001 From: Flo Edelmann Date: Mon, 8 Jul 2024 09:23:48 +0200 Subject: [PATCH 08/11] Discard changes to docs/rules/object-property-newline.md --- docs/rules/object-property-newline.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/rules/object-property-newline.md b/docs/rules/object-property-newline.md index c6e315c08..bfba0c0a2 100644 --- a/docs/rules/object-property-newline.md +++ b/docs/rules/object-property-newline.md @@ -36,4 +36,4 @@ This rule was introduced in eslint-plugin-vue v7.0.0 - [Rule source](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/object-property-newline.js) - [Test source](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/object-property-newline.js) -Taken with ❤️ [from ESLint Stylistic](https://eslint.style/rules/js/object-property-newline) +Taken with ❤️ [from ESLint Stylistic](https://eslint.style/rules/ts/object-property-newline) From 4a66d2e993195df3d9de075e3061855302402f6b Mon Sep 17 00:00:00 2001 From: ItMaga Date: Wed, 10 Jul 2024 16:59:32 +0300 Subject: [PATCH 09/11] feat: improve messages and accurate loc --- lib/rules/require-default-export.js | 42 +++++++++++------- tests/lib/rules/require-default-export.js | 54 ++++++++++++++++++----- 2 files changed, 70 insertions(+), 26 deletions(-) diff --git a/lib/rules/require-default-export.js b/lib/rules/require-default-export.js index 4053f16bf..5c5402008 100644 --- a/lib/rules/require-default-export.js +++ b/lib/rules/require-default-export.js @@ -17,7 +17,8 @@ module.exports = { fixable: null, schema: [], messages: { - mustDefaultExport: 'The component must be the default export.' + missing: 'Missing default export.', + mustBeDefaultExport: 'Component must be the default export.' } }, /** @param {RuleContext} context */ @@ -36,23 +37,32 @@ module.exports = { } let hasDefaultExport = false + let hasDefinedComponent = false - return { - 'Program > ExportDefaultDeclaration'() { - hasDefaultExport = true - }, - - /** - * @param {Program} node - */ - 'Program:exit'(node) { - if (!hasDefaultExport && node.body.length > 0) { - context.report({ - loc: { line: 1, column: 0 }, - messageId: 'mustDefaultExport' - }) + return utils.compositingVisitors( + utils.defineVueVisitor(context, { + onVueObjectExit() { + hasDefinedComponent = true + } + }), + + { + 'Program > ExportDefaultDeclaration'() { + hasDefaultExport = true + }, + + /** + * @param {Program} node + */ + 'Program:exit'(node) { + if (!hasDefaultExport && node.body.length > 0) { + context.report({ + loc: node.tokens[node.tokens.length - 1].loc, + messageId: hasDefinedComponent ? 'mustBeDefaultExport' : 'missing' + }) + } } } - } + ) } } diff --git a/tests/lib/rules/require-default-export.js b/tests/lib/rules/require-default-export.js index 438f057ee..279af4a38 100644 --- a/tests/lib/rules/require-default-export.js +++ b/tests/lib/rules/require-default-export.js @@ -86,8 +86,11 @@ tester.run('require-default-export', rule, { `, errors: [ { - messageId: 'mustDefaultExport', - line: 1 + messageId: 'missing', + line: 4, + endLine: 4, + column: 7, + endColumn: 16 } ] }, @@ -100,8 +103,11 @@ tester.run('require-default-export', rule, { `, errors: [ { - messageId: 'mustDefaultExport', - line: 1 + messageId: 'missing', + line: 4, + endLine: 4, + column: 7, + endColumn: 16 } ] }, @@ -116,8 +122,11 @@ tester.run('require-default-export', rule, { `, errors: [ { - messageId: 'mustDefaultExport', - line: 1 + messageId: 'missing', + line: 6, + endLine: 6, + column: 7, + endColumn: 16 } ] }, @@ -131,8 +140,11 @@ tester.run('require-default-export', rule, { `, errors: [ { - messageId: 'mustDefaultExport', - line: 1 + messageId: 'missing', + line: 5, + endLine: 5, + column: 7, + endColumn: 16 } ] }, @@ -147,8 +159,30 @@ tester.run('require-default-export', rule, { `, errors: [ { - messageId: 'mustDefaultExport', - line: 1 + messageId: 'mustBeDefaultExport', + line: 6, + endLine: 6, + column: 7, + endColumn: 16 + } + ] + }, + { + filename: 'test.vue', + code: ` + + `, + errors: [ + { + messageId: 'mustBeDefaultExport', + line: 6, + endLine: 6, + column: 7, + endColumn: 16 } ] } From c0dd101fcfe59dcd49be01f55254739a211b90a1 Mon Sep 17 00:00:00 2001 From: ItMaga Date: Wed, 10 Jul 2024 17:02:26 +0300 Subject: [PATCH 10/11] docs: add related rule to one-component-per-file --- docs/rules/one-component-per-file.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/rules/one-component-per-file.md b/docs/rules/one-component-per-file.md index 6fbede339..c5e94fbd8 100644 --- a/docs/rules/one-component-per-file.md +++ b/docs/rules/one-component-per-file.md @@ -49,6 +49,11 @@ export default { Nothing. + +## :couple: Related Rules + +- [vue/require-default-export](./require-default-export.md) + ## :books: Further Reading - [Style guide - Component files](https://vuejs.org/style-guide/rules-strongly-recommended.html#component-files) From 1c706a15ebb70487ff120ea4c2375d9f7468042f Mon Sep 17 00:00:00 2001 From: ItMaga Date: Wed, 10 Jul 2024 17:04:55 +0300 Subject: [PATCH 11/11] chore: remove empty line --- docs/rules/one-component-per-file.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/rules/one-component-per-file.md b/docs/rules/one-component-per-file.md index c5e94fbd8..5e6b37518 100644 --- a/docs/rules/one-component-per-file.md +++ b/docs/rules/one-component-per-file.md @@ -49,7 +49,6 @@ export default { Nothing. - ## :couple: Related Rules - [vue/require-default-export](./require-default-export.md)