Skip to content

Commit 617139e

Browse files
privatenumbermichalsnik
authored andcommitted
⭐️New: Add rule no-boolean-default (#612)
* no-boolean-default * Rule files * PR changes * Added docs * Added more tests * Update implementation * Update config and docs
1 parent ae03c28 commit 617139e

File tree

5 files changed

+306
-0
lines changed

5 files changed

+306
-0
lines changed

docs/rules/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ For example:
149149
| [vue/eqeqeq](./eqeqeq.md) | require the use of `===` and `!==` | :wrench: |
150150
| [vue/key-spacing](./key-spacing.md) | enforce consistent spacing between keys and values in object literal properties | :wrench: |
151151
| [vue/match-component-file-name](./match-component-file-name.md) | require component name property to match its file name | |
152+
| [vue/no-boolean-default](./no-boolean-default.md) | disallow boolean defaults | :wrench: |
152153
| [vue/no-restricted-syntax](./no-restricted-syntax.md) | disallow specified syntax | |
153154
| [vue/object-curly-spacing](./object-curly-spacing.md) | enforce consistent spacing inside braces | :wrench: |
154155
| [vue/require-direct-export](./require-direct-export.md) | require the component to be directly exported | |

docs/rules/no-boolean-default.md

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
---
2+
pageClass: rule-details
3+
sidebarDepth: 0
4+
title: vue/no-boolean-default
5+
description: disallow boolean defaults
6+
---
7+
# vue/no-boolean-default
8+
> disallow boolean defaults
9+
10+
- :wrench: The `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) can automatically fix some of the problems reported by this rule.
11+
12+
The rule prevents Boolean props from having a default value.
13+
14+
15+
## :book: Rule Details
16+
The rule is to enforce the HTML standard of always defaulting boolean attributes to false.
17+
18+
<eslint-code-block fix :rules="{'vue/no-boolean-default': ['error']}">
19+
20+
```vue
21+
<script>
22+
export default {
23+
props: {
24+
foo: {
25+
type: Boolean,
26+
default: true
27+
},
28+
bar: {
29+
type: Boolean
30+
}
31+
}
32+
}
33+
</script>
34+
```
35+
36+
</eslint-code-block>
37+
38+
## :wrench: Options
39+
- `'no-default'` (default) allows a prop definition object, but enforces that the `default` property not be defined.
40+
- `'default-false'` enforces that the default can be set but must be set to `false`.
41+
42+
```json
43+
"vue/no-boolean-default": ["error", "no-default|default-false"]
44+
```
45+
46+
## :mag: Implementation
47+
48+
- [Rule source](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/no-boolean-default.js)
49+
- [Test source](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/no-boolean-default.js)

lib/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ module.exports = {
3232
'mustache-interpolation-spacing': require('./rules/mustache-interpolation-spacing'),
3333
'name-property-casing': require('./rules/name-property-casing'),
3434
'no-async-in-computed-properties': require('./rules/no-async-in-computed-properties'),
35+
'no-boolean-default': require('./rules/no-boolean-default'),
3536
'no-confusing-v-for-v-if': require('./rules/no-confusing-v-for-v-if'),
3637
'no-dupe-keys': require('./rules/no-dupe-keys'),
3738
'no-duplicate-attributes': require('./rules/no-duplicate-attributes'),

lib/rules/no-boolean-default.js

+92
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/**
2+
* @fileoverview Prevents boolean defaults from being set
3+
* @author Hiroki Osame
4+
*/
5+
'use strict'
6+
7+
const utils = require('../utils')
8+
9+
// ------------------------------------------------------------------------------
10+
// Rule Definition
11+
// ------------------------------------------------------------------------------
12+
13+
function isBooleanProp (prop) {
14+
return (
15+
prop.type === 'Property' &&
16+
prop.key.type === 'Identifier' &&
17+
prop.key.name === 'type' &&
18+
prop.value.type === 'Identifier' &&
19+
prop.value.name === 'Boolean'
20+
)
21+
}
22+
23+
function getBooleanProps (props) {
24+
return props
25+
.filter(prop => (
26+
prop.value &&
27+
prop.value.properties &&
28+
prop.value.properties.find(isBooleanProp)
29+
))
30+
}
31+
32+
function getDefaultNode (propDef) {
33+
return propDef.value.properties.find(p => {
34+
return (
35+
p.type === 'Property' &&
36+
p.key.type === 'Identifier' &&
37+
p.key.name === 'default'
38+
)
39+
})
40+
}
41+
42+
module.exports = {
43+
meta: {
44+
type: 'suggestion',
45+
docs: {
46+
description: 'disallow boolean defaults',
47+
category: undefined,
48+
url: 'https://eslint.vuejs.org/rules/no-boolean-default.html'
49+
},
50+
fixable: 'code',
51+
schema: [
52+
{
53+
enum: ['default-false', 'no-default']
54+
}
55+
]
56+
},
57+
58+
create (context) {
59+
return utils.executeOnVueComponent(context, (obj) => {
60+
const props = utils.getComponentProps(obj)
61+
const booleanProps = getBooleanProps(props)
62+
63+
if (!booleanProps.length) return
64+
65+
const booleanType = context.options[0] || 'no-default'
66+
67+
booleanProps.forEach((propDef) => {
68+
const defaultNode = getDefaultNode(propDef)
69+
70+
switch (booleanType) {
71+
case 'no-default':
72+
if (defaultNode) {
73+
context.report({
74+
node: defaultNode,
75+
message: 'Boolean prop should not set a default (Vue defaults it to false).'
76+
})
77+
}
78+
break
79+
80+
case 'default-false':
81+
if (defaultNode.value.value !== false) {
82+
context.report({
83+
node: defaultNode,
84+
message: 'Boolean prop should be defaulted to false.'
85+
})
86+
}
87+
break
88+
}
89+
})
90+
})
91+
}
92+
}

tests/lib/rules/no-boolean-default.js

+163
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
/**
2+
* @fileoverview Prevents boolean defaults from being set
3+
* @author Hiroki Osame
4+
*/
5+
'use strict'
6+
7+
// ------------------------------------------------------------------------------
8+
// Requirements
9+
// ------------------------------------------------------------------------------
10+
11+
var rule = require('../../../lib/rules/no-boolean-default')
12+
13+
var RuleTester = require('eslint').RuleTester
14+
15+
// ------------------------------------------------------------------------------
16+
// Tests
17+
// ------------------------------------------------------------------------------
18+
19+
var ruleTester = new RuleTester({
20+
parserOptions: {
21+
ecmaVersion: 2018,
22+
sourceType: 'module'
23+
}
24+
})
25+
ruleTester.run('no-boolean-default', rule, {
26+
27+
valid: [
28+
{
29+
filename: 'test.vue',
30+
code: `
31+
export default {
32+
props: {
33+
enabled: Boolean
34+
}
35+
}
36+
`
37+
},
38+
{
39+
filename: 'test.vue',
40+
code: `
41+
const props = {};
42+
export default {
43+
props: {
44+
...props,
45+
enabled: Boolean
46+
}
47+
}
48+
`
49+
},
50+
{
51+
filename: 'test.vue',
52+
code: `
53+
const data = {};
54+
export default {
55+
props: {
56+
enabled: {
57+
type: Boolean,
58+
...data
59+
}
60+
}
61+
}
62+
`,
63+
options: ['no-default']
64+
},
65+
{
66+
filename: 'test.vue',
67+
code: `
68+
const data = {};
69+
export default {
70+
props: {
71+
enabled: {
72+
type: Boolean,
73+
default: false,
74+
...data
75+
}
76+
}
77+
}
78+
`,
79+
options: ['default-false']
80+
},
81+
{
82+
filename: 'test.vue',
83+
code: `
84+
const data = {};
85+
export default {
86+
props: {
87+
enabled: data
88+
}
89+
}
90+
`
91+
},
92+
{
93+
filename: 'test.vue',
94+
code: `
95+
const data = {};
96+
export default {
97+
props: {
98+
enabled: {
99+
...data
100+
}
101+
}
102+
}
103+
`
104+
}
105+
],
106+
107+
invalid: [
108+
{
109+
filename: 'test.vue',
110+
code: `
111+
export default {
112+
props: {
113+
enabled: {
114+
type: Boolean,
115+
default: true,
116+
}
117+
}
118+
}
119+
`,
120+
options: ['default-false'],
121+
errors: [{
122+
message: 'Boolean prop should be defaulted to false.',
123+
line: 6
124+
}]
125+
},
126+
{
127+
filename: 'test.vue',
128+
code: `
129+
export default {
130+
props: {
131+
enabled: {
132+
type: Boolean,
133+
default: null,
134+
}
135+
}
136+
}
137+
`,
138+
options: ['default-false'],
139+
errors: [{
140+
message: 'Boolean prop should be defaulted to false.',
141+
line: 6
142+
}]
143+
},
144+
{
145+
filename: 'test.vue',
146+
code: `
147+
export default {
148+
props: {
149+
enabled: {
150+
type: Boolean,
151+
default: false,
152+
}
153+
}
154+
}
155+
`,
156+
options: ['no-default'],
157+
errors: [{
158+
message: 'Boolean prop should not set a default (Vue defaults it to false).',
159+
line: 6
160+
}]
161+
}
162+
]
163+
})

0 commit comments

Comments
 (0)