Skip to content

Commit 426f5af

Browse files
committed
Add vue/require-default-export rule
1 parent d7169e1 commit 426f5af

11 files changed

+245
-2
lines changed

docs/rules/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ Rules in this category are enabled for all presets provided by eslint-plugin-vue
9595
| [vue/no-watch-after-await](./no-watch-after-await.md) | disallow asynchronously registered `watch` | | :three::hammer: |
9696
| [vue/prefer-import-from-vue](./prefer-import-from-vue.md) | enforce import from 'vue' instead of import from '@vue/*' | :wrench: | :three::hammer: |
9797
| [vue/require-component-is](./require-component-is.md) | require `v-bind:is` of `<component>` elements | | :three::two::warning: |
98+
| [vue/require-default-export](./require-default-export.md) | require default export | | :three::two::warning: |
9899
| [vue/require-prop-type-constructor](./require-prop-type-constructor.md) | require prop type to be a constructor | :wrench: | :three::two::hammer: |
99100
| [vue/require-render-return](./require-render-return.md) | enforce render function to always return value | | :three::two::warning: |
100101
| [vue/require-slots-as-functions](./require-slots-as-functions.md) | enforce properties of `$slots` to be used as a function | | :three::warning: |

docs/rules/object-curly-newline.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,4 @@ This rule was introduced in eslint-plugin-vue v7.0.0
3636
- [Rule source](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/object-curly-newline.js)
3737
- [Test source](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/object-curly-newline.js)
3838

39-
<sup>Taken with ❤️ [from ESLint Stylistic](https://eslint.style/rules/js/object-curly-newline)</sup>
39+
<sup>Taken with ❤️ [from ESLint Stylistic](https://eslint.style/rules/ts/object-curly-newline)</sup>

docs/rules/object-property-newline.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,4 @@ This rule was introduced in eslint-plugin-vue v7.0.0
3636
- [Rule source](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/object-property-newline.js)
3737
- [Test source](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/object-property-newline.js)
3838

39-
<sup>Taken with ❤️ [from ESLint Stylistic](https://eslint.style/rules/js/object-property-newline)</sup>
39+
<sup>Taken with ❤️ [from ESLint Stylistic](https://eslint.style/rules/ts/object-property-newline)</sup>

docs/rules/require-default-export.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
---
2+
pageClass: rule-details
3+
sidebarDepth: 0
4+
title: vue/require-default-export
5+
description: require default export
6+
---
7+
8+
# vue/require-default-export
9+
10+
> require default export
11+
12+
- :exclamation: <badge text="This rule has not been released yet." vertical="middle" type="error"> _**This rule has not been released yet.**_ </badge>
13+
- :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"]`.
14+
15+
## :book: Rule Details
16+
17+
This rule reports when a Vue component does not have a default export, if the component is not defined as `<script setup>`.
18+
19+
<eslint-code-block :rules="{'vue/require-default-export': ['error']}">
20+
21+
```vue
22+
<!-- ✗ BAD -->
23+
<script>
24+
const foo = 'foo';
25+
</script>
26+
```
27+
28+
</eslint-code-block>
29+
30+
<eslint-code-block :rules="{'vue/require-default-export': ['error']}">
31+
32+
```vue
33+
<!-- ✓ GOOD -->
34+
<script>
35+
export default {
36+
data() {
37+
return {
38+
foo: 'foo'
39+
};
40+
}
41+
};
42+
</script>
43+
```
44+
45+
</eslint-code-block>
46+
47+
## :wrench: Options
48+
49+
Nothing.
50+
51+
## :mag: Implementation
52+
53+
- [Rule source](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/require-default-export.js)
54+
- [Test source](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/require-default-export.js)

lib/configs/flat/vue2-essential.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ module.exports = [
4646
'vue/no-v-model-argument': 'error',
4747
'vue/no-v-text-v-html-on-component': 'error',
4848
'vue/require-component-is': 'error',
49+
'vue/require-default-export': 'error',
4950
'vue/require-prop-type-constructor': 'error',
5051
'vue/require-render-return': 'error',
5152
'vue/require-v-for-key': 'error',

lib/configs/flat/vue3-essential.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ module.exports = [
6161
'vue/no-watch-after-await': 'error',
6262
'vue/prefer-import-from-vue': 'error',
6363
'vue/require-component-is': 'error',
64+
'vue/require-default-export': 'error',
6465
'vue/require-prop-type-constructor': 'error',
6566
'vue/require-render-return': 'error',
6667
'vue/require-slots-as-functions': 'error',

lib/configs/vue2-essential.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ module.exports = {
4141
'vue/no-v-model-argument': 'error',
4242
'vue/no-v-text-v-html-on-component': 'error',
4343
'vue/require-component-is': 'error',
44+
'vue/require-default-export': 'error',
4445
'vue/require-prop-type-constructor': 'error',
4546
'vue/require-render-return': 'error',
4647
'vue/require-v-for-key': 'error',

lib/configs/vue3-essential.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ module.exports = {
5656
'vue/no-watch-after-await': 'error',
5757
'vue/prefer-import-from-vue': 'error',
5858
'vue/require-component-is': 'error',
59+
'vue/require-default-export': 'error',
5960
'vue/require-prop-type-constructor': 'error',
6061
'vue/require-render-return': 'error',
6162
'vue/require-slots-as-functions': 'error',

lib/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ const plugin = {
208208
'prop-name-casing': require('./rules/prop-name-casing'),
209209
'quote-props': require('./rules/quote-props'),
210210
'require-component-is': require('./rules/require-component-is'),
211+
'require-default-export': require('./rules/require-default-export'),
211212
'require-default-prop': require('./rules/require-default-prop'),
212213
'require-direct-export': require('./rules/require-direct-export'),
213214
'require-emit-validator': require('./rules/require-emit-validator'),

lib/rules/require-default-export.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/**
2+
* @author ItMaga
3+
* See LICENSE file in root directory for full license.
4+
*/
5+
'use strict'
6+
7+
const utils = require('../utils')
8+
9+
module.exports = {
10+
meta: {
11+
type: 'problem',
12+
docs: {
13+
description: 'require default export',
14+
categories: ['vue3-essential', 'vue2-essential'],
15+
url: 'https://eslint.vuejs.org/rules/require-default-export.html'
16+
},
17+
fixable: null,
18+
schema: [],
19+
messages: {
20+
missing: 'Missing default export.'
21+
}
22+
},
23+
/** @param {RuleContext} context */
24+
create(context) {
25+
if (utils.isScriptSetup(context)) {
26+
return {}
27+
}
28+
29+
return {
30+
/**
31+
* @param {Program} node
32+
*/
33+
'Program:exit'(node) {
34+
const hasDefaultExport = node.body.some(
35+
(item) => item.type === 'ExportDefaultDeclaration'
36+
)
37+
38+
if (!hasDefaultExport) {
39+
context.report({
40+
loc: { line: 1, column: 0 },
41+
messageId: 'missing'
42+
})
43+
}
44+
}
45+
}
46+
}
47+
}
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
/**
2+
* @author ItMaga
3+
* See LICENSE file in root directory for full license.
4+
*/
5+
'use strict'
6+
7+
const RuleTester = require('../../eslint-compat').RuleTester
8+
const rule = require('../../../lib/rules/require-default-export')
9+
10+
const tester = new RuleTester({
11+
languageOptions: {
12+
parser: require('vue-eslint-parser'),
13+
ecmaVersion: 2020,
14+
sourceType: 'module'
15+
}
16+
})
17+
18+
tester.run('require-default-export', rule, {
19+
valid: [
20+
{
21+
filename: 'test.vue',
22+
code: `
23+
<script>
24+
import { ref } from 'vue';
25+
26+
export default {}
27+
</script>
28+
`
29+
},
30+
{
31+
filename: 'test.vue',
32+
code: `
33+
<script setup>
34+
const foo = 'foo';
35+
</script>
36+
`
37+
},
38+
{
39+
filename: 'test.vue',
40+
code: `
41+
<script>
42+
const component = {};
43+
44+
export default component;
45+
</script>
46+
`
47+
},
48+
{
49+
filename: 'test.vue',
50+
code: `
51+
<script>
52+
import {defineComponent} from 'vue';
53+
54+
export default defineComponent({});
55+
</script>
56+
`
57+
}
58+
],
59+
invalid: [
60+
{
61+
filename: 'test.vue',
62+
code: `
63+
<script>
64+
const foo = 'foo';
65+
</script>
66+
`,
67+
errors: [
68+
{
69+
messageId: 'missing',
70+
line: 1
71+
}
72+
]
73+
},
74+
{
75+
filename: 'test.vue',
76+
code: `
77+
<script>
78+
export const foo = 'foo';
79+
</script>
80+
`,
81+
errors: [
82+
{
83+
messageId: 'missing',
84+
line: 1
85+
}
86+
]
87+
},
88+
{
89+
filename: 'test.vue',
90+
code: `
91+
<script>
92+
const foo = 'foo';
93+
94+
export { foo };
95+
</script>
96+
`,
97+
errors: [
98+
{
99+
messageId: 'missing',
100+
line: 1
101+
}
102+
]
103+
},
104+
{
105+
filename: 'test.vue',
106+
code: `
107+
<script>
108+
export const foo = 'foo';
109+
export const bar = 'bar';
110+
</script>
111+
`,
112+
errors: [
113+
{
114+
messageId: 'missing',
115+
line: 1
116+
}
117+
]
118+
},
119+
{
120+
filename: 'test.vue',
121+
code: `
122+
<script>
123+
import { defineComponent } from 'vue';
124+
125+
export const component = defineComponent({});
126+
</script>
127+
`,
128+
errors: [
129+
{
130+
messageId: 'missing',
131+
line: 1
132+
}
133+
]
134+
}
135+
]
136+
})

0 commit comments

Comments
 (0)