Skip to content

Commit 6d8a2fb

Browse files
committed
New: Add vue/require-shorthand-boolean-prop rule
1 parent 1ffcd01 commit 6d8a2fb

File tree

5 files changed

+298
-0
lines changed

5 files changed

+298
-0
lines changed

docs/rules/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,7 @@ For example:
277277
| [vue/padding-line-between-blocks](./padding-line-between-blocks.md) | require or disallow padding lines between blocks | :wrench: |
278278
| [vue/require-direct-export](./require-direct-export.md) | require the component to be directly exported | |
279279
| [vue/require-name-property](./require-name-property.md) | require a name property in Vue components | |
280+
| [vue/require-shorthand-boolean-prop](./require-shorthand-boolean-prop.md) | enforce or forbid passing `true` value to a prop | |
280281
| [vue/script-indent](./script-indent.md) | enforce consistent indentation in `<script>` | :wrench: |
281282
| [vue/sort-keys](./sort-keys.md) | enforce sort-keys in a manner that is compatible with order-in-components | |
282283
| [vue/space-infix-ops](./space-infix-ops.md) | require spacing around infix operators | :wrench: |
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/require-shorthand-boolean-prop
5+
description: enforce or forbid passing `true` value to a prop
6+
---
7+
# vue/require-shorthand-boolean-prop
8+
> enforce or forbid passing `true` value to a prop
9+
10+
## :book: Rule Details
11+
12+
This rule aims at enforcing usage of shorthand properties for `true` values in Vue templates.
13+
14+
<eslint-code-block :rules="{'vue/require-shorthand-boolean-prop': ['error']}">
15+
16+
```vue
17+
<template>
18+
<!-- ✓ GOOD -->
19+
<component
20+
isValid
21+
/>
22+
23+
<!-- ✗ BAD -->
24+
<component
25+
:isValid="true"
26+
/>
27+
</template>
28+
```
29+
30+
</eslint-code-block>
31+
32+
## :wrench: Options
33+
34+
```json
35+
{
36+
"vue/require-shorthand-boolean-prop": ["error", "always" | "never"]
37+
}
38+
```
39+
- `"always"` (default) ... Always use shorthand prop.
40+
- `"never"` ... Never use shorthand prop. Instead pass `true` explicitly.
41+
42+
### `"never"`
43+
44+
<eslint-code-block :rules="{'vue/require-shorthand-boolean-prop': ['error', 'never']}">
45+
46+
```vue
47+
<template>
48+
<!-- ✓ GOOD -->
49+
<component
50+
:isValid="true"
51+
isValid
52+
/>
53+
54+
<!-- ✗ BAD -->
55+
<component
56+
isValid
57+
/>
58+
</template>
59+
```
60+
61+
</eslint-code-block>
62+
63+
## :mag: Implementation
64+
65+
- [Rule source](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/require-shorthand-boolean-prop.js)
66+
- [Test source](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/require-shorthand-boolean-prop.js)

lib/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ module.exports = {
8282
'require-prop-type-constructor': require('./rules/require-prop-type-constructor'),
8383
'require-prop-types': require('./rules/require-prop-types'),
8484
'require-render-return': require('./rules/require-render-return'),
85+
'require-shorthand-boolean-prop': require('./rules/require-shorthand-boolean-prop'),
8586
'require-v-for-key': require('./rules/require-v-for-key'),
8687
'require-valid-default-prop': require('./rules/require-valid-default-prop'),
8788
'return-in-computed-property': require('./rules/return-in-computed-property'),
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/**
2+
* @fileoverview Enforce or forbid passing `true` value to a prop
3+
* @author Anton Veselev
4+
*/
5+
'use strict'
6+
7+
const utils = require('../utils')
8+
9+
// ------------------------------------------------------------------------------
10+
// Rule Definition
11+
// ------------------------------------------------------------------------------
12+
13+
module.exports = {
14+
meta: {
15+
type: 'suggestion',
16+
docs: {
17+
description: 'enforce or forbid passing `true` value to a prop',
18+
categories: ['vue3-uncategorized', 'uncategorized'],
19+
recommended: false,
20+
url: 'https://eslint.vuejs.org/rules/require-shorthand-boolean-prop.html'
21+
},
22+
fixable: 'code',
23+
schema: [
24+
{
25+
enum: ['always', 'never']
26+
}
27+
]
28+
},
29+
30+
create (context) {
31+
const isAlways = context.options[0] !== 'never'
32+
33+
return utils.defineTemplateBodyVisitor(context, {
34+
VStartTag (node) {
35+
for (const attr of node.attributes) {
36+
if (attr.value === null) {
37+
if (!isAlways) {
38+
context.report({
39+
node,
40+
loc: attr.loc,
41+
message: 'Unexpected shorthand prop.',
42+
fix (fixer) {
43+
const { rawName } = attr.key || {}
44+
return rawName
45+
? fixer.replaceTextRange(attr.range, `:${rawName}="true"`)
46+
: null
47+
}
48+
})
49+
}
50+
continue
51+
}
52+
const { expression } = attr.value
53+
if (expression && expression.value === true) {
54+
if (isAlways) {
55+
context.report({
56+
node,
57+
loc: attr.loc,
58+
message: "Unexpected 'true' value.",
59+
fix (fixer) {
60+
const { rawName } = (attr.key || {}).argument || {}
61+
return rawName
62+
? fixer.replaceTextRange(attr.range, rawName)
63+
: null
64+
}
65+
})
66+
}
67+
continue
68+
}
69+
}
70+
}
71+
})
72+
}
73+
}
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
/**
2+
* @fileoverview Enforce or forbid passing `true` value to a prop
3+
* @author Anton Veselev
4+
*/
5+
'use strict'
6+
7+
// ------------------------------------------------------------------------------
8+
// Requirements
9+
// ------------------------------------------------------------------------------
10+
11+
const rule = require('../../../lib/rules/require-shorthand-boolean-prop')
12+
13+
const { RuleTester } = require('eslint')
14+
15+
// ------------------------------------------------------------------------------
16+
// Tests
17+
// ------------------------------------------------------------------------------
18+
19+
const ruleTester = new RuleTester({
20+
parser: require.resolve('vue-eslint-parser'),
21+
parserOptions: { ecmaVersion: 2015 }
22+
})
23+
24+
ruleTester.run('require-shorthand-boolean-prop', rule, {
25+
26+
valid: [
27+
{
28+
code: `
29+
<template>
30+
<component />
31+
</template>
32+
`
33+
},
34+
{
35+
code: `
36+
<template>
37+
<component
38+
isValid
39+
/>
40+
</template>
41+
`
42+
},
43+
{
44+
code: `
45+
<template>
46+
<component
47+
isValid
48+
/>
49+
</template>
50+
`,
51+
options: ['always']
52+
},
53+
{
54+
code: `
55+
<template>
56+
<component
57+
:isValid="false"
58+
/>
59+
</template>
60+
`,
61+
options: ['always']
62+
},
63+
{
64+
code: `
65+
<template>
66+
<component
67+
:isValid="true"
68+
/>
69+
</template>
70+
`,
71+
options: ['never']
72+
},
73+
{
74+
code: `
75+
<template>
76+
<component
77+
:isValid="false"
78+
/>
79+
</template>
80+
`,
81+
options: ['never']
82+
},
83+
{
84+
code: `
85+
<template>
86+
<component
87+
str="true"
88+
/>
89+
</template>
90+
`
91+
},
92+
{
93+
code: `
94+
<template>
95+
<component
96+
str="true"
97+
/>
98+
</template>
99+
`,
100+
options: ['always']
101+
},
102+
{
103+
code: `
104+
<template>
105+
<component
106+
str="true"
107+
/>
108+
</template>
109+
`,
110+
options: ['never']
111+
}
112+
],
113+
114+
invalid: [
115+
{
116+
code: `
117+
<template>
118+
<component
119+
:isValid="true"
120+
/>
121+
</template>
122+
`,
123+
errors: [{
124+
message: "Unexpected 'true' value.",
125+
type: 'VStartTag'
126+
}]
127+
},
128+
{
129+
code: `
130+
<template>
131+
<component
132+
isValid
133+
/>
134+
</template>
135+
`,
136+
options: ['never'],
137+
errors: [{
138+
message: 'Unexpected shorthand prop.',
139+
type: 'VStartTag'
140+
}]
141+
},
142+
{
143+
code: `
144+
<template>
145+
<component
146+
:isValid="true"
147+
/>
148+
</template>
149+
`,
150+
options: ['always'],
151+
errors: [{
152+
message: "Unexpected 'true' value.",
153+
type: 'VStartTag'
154+
}]
155+
}
156+
]
157+
})

0 commit comments

Comments
 (0)