Skip to content

Commit 297d750

Browse files
committed
implements proposed max-props rule
1 parent f84b8ee commit 297d750

File tree

5 files changed

+285
-0
lines changed

5 files changed

+285
-0
lines changed

docs/rules/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,7 @@ For example:
223223
| [vue/match-component-file-name](./match-component-file-name.md) | require component name property to match its file name | :bulb: | :hammer: |
224224
| [vue/match-component-import-name](./match-component-import-name.md) | require the registered component name to match the imported component name | | :warning: |
225225
| [vue/max-lines-per-block](./max-lines-per-block.md) | enforce maximum number of lines in Vue SFC blocks | | :warning: |
226+
| [vue/max-props](./max-props.md) | enforce maximum number of props in Vue component | | :warning: |
226227
| [vue/new-line-between-multi-line-property](./new-line-between-multi-line-property.md) | enforce new lines between multi-line properties in Vue components | :wrench: | :lipstick: |
227228
| [vue/next-tick-style](./next-tick-style.md) | enforce Promise or callback style in `nextTick` | :wrench: | :hammer: |
228229
| [vue/no-bare-strings-in-template](./no-bare-strings-in-template.md) | disallow the use of bare strings in `<template>` | | :hammer: |

docs/rules/max-props.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
---
2+
pageClass: rule-details
3+
sidebarDepth: 0
4+
title: vue/max-props
5+
description: enforce maximum number of props in Vue component
6+
---
7+
8+
# vue/max-props
9+
10+
> enforce maximum number of props in Vue component
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+
14+
## :book: Rule Details
15+
16+
This rule enforces a maximum number of props in a Vue SFC, in order to aid in maintainability and reduce complexity.
17+
18+
19+
## :wrench: Options
20+
This rule takes an object, where you can specify the maximum number of props allowed in a Vue SFC.
21+
There is one property that can be specified for the object.
22+
23+
- `maxProps` ... Specify the maximum number of props in the `script` block.
24+
25+
### `{ maxProps: 1 }`
26+
27+
<eslint-code-block :rules="{'vue/max-props': ['error', { maxProps: 1 }]}">
28+
29+
```vue
30+
<!-- ✗ BAD -->
31+
<template>
32+
</template>
33+
34+
<script setup>
35+
defineProps({
36+
prop1: String,
37+
prop2: String,
38+
})
39+
</script>
40+
```
41+
42+
</eslint-code-block>
43+
44+
45+
### `{ maxProps: 5 }`
46+
47+
<eslint-code-block :rules="{'vue/max-props': ['error', { maxProps: 5 }]}">
48+
49+
```vue
50+
<!-- ✓ GOOD -->
51+
<script>
52+
defineProps({
53+
prop1: String
54+
})
55+
</script>
56+
```
57+
58+
</eslint-code-block>
59+
60+
61+
Nothing.
62+
63+
## :mag: Implementation
64+
65+
- [Rule source](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/max-props.js)
66+
- [Test source](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/max-props.js)

lib/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ module.exports = {
5757
'max-attributes-per-line': require('./rules/max-attributes-per-line'),
5858
'max-len': require('./rules/max-len'),
5959
'max-lines-per-block': require('./rules/max-lines-per-block'),
60+
'max-props': require('./rules/max-props'),
6061
'multi-word-component-names': require('./rules/multi-word-component-names'),
6162
'multiline-html-element-content-newline': require('./rules/multiline-html-element-content-newline'),
6263
'multiline-ternary': require('./rules/multiline-ternary'),

lib/rules/max-props.js

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/**
2+
* @author kevsommer Kevin Sommer
3+
* See LICENSE file in root directory for full license.
4+
*/
5+
'use strict'
6+
const utils = require('../utils')
7+
8+
module.exports = {
9+
meta: {
10+
type: 'problem',
11+
docs: {
12+
description: 'enforce maximum number of props in Vue component',
13+
categories: undefined,
14+
url: 'https://eslint.vuejs.org/rules/max-props.html'
15+
},
16+
fixable: null,
17+
schema: [
18+
{
19+
type: 'object',
20+
properties: {
21+
maxProps: {
22+
type: 'integer',
23+
minimum: 1
24+
}
25+
},
26+
additionalProperties: false
27+
}
28+
],
29+
messages: {
30+
tooManyProps:
31+
'Component has too many props ({{propCount}}). Maximum allowed is {{limit}}.'
32+
}
33+
},
34+
/** @param {RuleContext} context */
35+
create(context) {
36+
/**
37+
* @type {Record<string, number>}
38+
*/
39+
const option = context.options[0] || {}
40+
41+
/**
42+
*
43+
* @param {import('../utils').ComponentProp[]} props
44+
*/
45+
function checkMaxNumberOfProps(props) {
46+
if (props.length > option.maxProps && props[0].node) {
47+
context.report({
48+
node: props[0].node,
49+
messageId: 'tooManyProps',
50+
data: {
51+
propCount: props.length,
52+
limit: option.maxProps
53+
}
54+
})
55+
}
56+
}
57+
58+
return utils.compositingVisitors(
59+
utils.executeOnVueComponent(context, (obj) => {
60+
checkMaxNumberOfProps(utils.getComponentPropsFromOptions(obj))
61+
}),
62+
utils.defineScriptSetupVisitor(context, {
63+
onDefinePropsEnter(_, props) {
64+
checkMaxNumberOfProps(props)
65+
}
66+
})
67+
)
68+
}
69+
}

tests/lib/rules/max-props.js

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
/**
2+
* @author kevsommer Kevin Sommer
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/max-props')
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('max-props', rule, {
19+
valid: [
20+
{
21+
filename: 'test.vue',
22+
code: `
23+
<template>
24+
25+
</template>
26+
<script setup>
27+
defineProps({ prop1: '', prop2: '' })
28+
</script>
29+
`,
30+
options: [{ maxProps: 5 }]
31+
},
32+
{
33+
filename: 'test.vue',
34+
code: `
35+
<template>
36+
37+
</template>
38+
<script>
39+
export default {
40+
props: {
41+
prop1: String,
42+
prop2: String
43+
}
44+
}
45+
</script>
46+
`,
47+
options: [{ maxProps: 5 }]
48+
},
49+
{
50+
filename: 'test.vue',
51+
code: `
52+
<template>
53+
54+
</template>
55+
<script>
56+
export default {
57+
props: {
58+
prop1: String,
59+
prop2: String,
60+
prop3: String,
61+
prop4: String,
62+
prop5: String
63+
}
64+
}
65+
</script>
66+
`,
67+
options: [{ maxProps: 5 }]
68+
},
69+
{
70+
filename: 'test.vue',
71+
code: `
72+
<template>
73+
74+
</template>
75+
<script>
76+
export default {
77+
props: {}
78+
}
79+
</script>
80+
`,
81+
options: [{ maxProps: 5 }]
82+
},
83+
{
84+
filename: 'test.vue',
85+
code: `
86+
<template>
87+
88+
</template>
89+
<script setup>
90+
defineProps({})
91+
</script>
92+
`,
93+
options: [{ maxProps: 5 }]
94+
},
95+
{
96+
filename: 'test.vue',
97+
code: `
98+
<template>
99+
100+
</template>
101+
<script>
102+
</script>
103+
`,
104+
options: [{ maxProps: 5 }]
105+
}
106+
],
107+
invalid: [
108+
{
109+
filename: 'test.vue',
110+
code: `
111+
<template>
112+
</template>
113+
<script setup>
114+
defineProps({ prop1: '', prop2: '' })
115+
</script>
116+
`,
117+
options: [{ maxProps: 1 }],
118+
errors: [
119+
{
120+
message: 'Component has too many props (2). Maximum allowed is 1.',
121+
line: 5
122+
}
123+
]
124+
},
125+
{
126+
filename: 'test.vue',
127+
code: `
128+
<template>
129+
</template>
130+
<script>
131+
export default {
132+
props: {
133+
prop1: String,
134+
prop2: String
135+
}
136+
}
137+
</script>
138+
`,
139+
options: [{ maxProps: 1 }],
140+
errors: [
141+
{
142+
message: 'Component has too many props (2). Maximum allowed is 1.',
143+
line: 7
144+
}
145+
]
146+
}
147+
]
148+
})

0 commit comments

Comments
 (0)