Skip to content

Commit ebbabd2

Browse files
waynzhFloEdelmann
andauthored
Add new vue/no-negated-condition rule (#2795)
Co-authored-by: Flo Edelmann <[email protected]>
1 parent e2d50c7 commit ebbabd2

File tree

6 files changed

+219
-0
lines changed

6 files changed

+219
-0
lines changed

.changeset/true-pumas-open.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'eslint-plugin-vue': minor
3+
---
4+
5+
Added new [`vue/no-negated-condition`](https://eslint.vuejs.org/rules/no-negated-condition.html) rule

docs/rules/index.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,7 @@ The following rules extend the rules provided by ESLint itself and apply them to
327327
| [vue/no-implicit-coercion] | Disallow shorthand type conversions in `<template>` | :wrench::bulb: | :hammer: |
328328
| [vue/no-irregular-whitespace] | disallow irregular whitespace in `.vue` files | | :warning: |
329329
| [vue/no-loss-of-precision] | Disallow literal numbers that lose precision in `<template>` | | :warning: |
330+
| [vue/no-negated-condition] | Disallow negated conditions in `<template>` | | :hammer: |
330331
| [vue/no-restricted-syntax] | Disallow specified syntax in `<template>` | | :hammer: |
331332
| [vue/no-sparse-arrays] | Disallow sparse arrays in `<template>` | | :warning: |
332333
| [vue/no-useless-concat] | Disallow unnecessary concatenation of literals or template literals in `<template>` | | :hammer: |
@@ -482,6 +483,7 @@ The following rules extend the rules provided by ESLint itself and apply them to
482483
[vue/no-multiple-slot-args]: ./no-multiple-slot-args.md
483484
[vue/no-multiple-template-root]: ./no-multiple-template-root.md
484485
[vue/no-mutating-props]: ./no-mutating-props.md
486+
[vue/no-negated-condition]: ./no-negated-condition.md
485487
[vue/no-parsing-error]: ./no-parsing-error.md
486488
[vue/no-potential-component-option-typo]: ./no-potential-component-option-typo.md
487489
[vue/no-ref-as-operand]: ./no-ref-as-operand.md

docs/rules/no-negated-condition.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
---
2+
pageClass: rule-details
3+
sidebarDepth: 0
4+
title: vue/no-negated-condition
5+
description: Disallow negated conditions in `<template>`
6+
---
7+
8+
# vue/no-negated-condition
9+
10+
> Disallow negated conditions in `<template>`
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 is the same rule as core [no-negated-condition] rule but it applies to the expressions in `<template>`.
17+
18+
## :couple: Related Rules
19+
20+
- [unicorn/no-negated-condition](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-negated-condition.md)
21+
22+
## :books: Further Reading
23+
24+
- [no-negated-condition]
25+
26+
[no-negated-condition]: https://eslint.org/docs/rules/no-negated-condition
27+
28+
## :mag: Implementation
29+
30+
- [Rule source](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/no-negated-condition.js)
31+
- [Test source](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/no-negated-condition.js)
32+
33+
<sup>Taken with ❤️ [from ESLint core](https://eslint.org/docs/latest/rules/no-negated-condition)</sup>

lib/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ const plugin = {
141141
'no-multiple-slot-args': require('./rules/no-multiple-slot-args'),
142142
'no-multiple-template-root': require('./rules/no-multiple-template-root'),
143143
'no-mutating-props': require('./rules/no-mutating-props'),
144+
'no-negated-condition': require('./rules/no-negated-condition'),
144145
'no-parsing-error': require('./rules/no-parsing-error'),
145146
'no-potential-component-option-typo': require('./rules/no-potential-component-option-typo'),
146147
'no-ref-as-operand': require('./rules/no-ref-as-operand'),

lib/rules/no-negated-condition.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/**
2+
* @author Wayne Zhang
3+
* See LICENSE file in root directory for full license.
4+
*/
5+
'use strict'
6+
7+
const { wrapCoreRule } = require('../utils')
8+
9+
// eslint-disable-next-line internal/no-invalid-meta
10+
module.exports = wrapCoreRule('no-negated-condition', {
11+
applyDocument: true
12+
})
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
/**
2+
* @author Wayne Zhang
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/no-negated-condition')
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('no-negated-condition', rule, {
19+
valid: [
20+
{
21+
filename: 'test.vue',
22+
code: `
23+
<template>
24+
<div :class="foo ? 'baz' : 'bar'" />
25+
</template>
26+
`
27+
},
28+
{
29+
filename: 'test.vue',
30+
code: `
31+
<template>
32+
<div :style="{ color: isActive ? 'red' : 'blue' }" />
33+
</template>
34+
`
35+
}
36+
],
37+
invalid: [
38+
{
39+
filename: 'test.vue',
40+
code: `
41+
<template>
42+
<div :class="!foo ? 'bar' : 'baz'" />
43+
</template>
44+
`,
45+
errors: [
46+
{
47+
message: 'Unexpected negated condition.',
48+
line: 3,
49+
column: 22,
50+
endLine: 3,
51+
endColumn: 42
52+
}
53+
]
54+
},
55+
{
56+
filename: 'test.vue',
57+
code: `
58+
<template>
59+
<div :style="{
60+
'display': !isVisible ? 'none' : 'block',
61+
'color': 'red'
62+
}" />
63+
</template>
64+
`,
65+
errors: [
66+
{
67+
message: 'Unexpected negated condition.',
68+
line: 4,
69+
column: 22,
70+
endLine: 4,
71+
endColumn: 51
72+
}
73+
]
74+
},
75+
{
76+
filename: 'test.vue',
77+
code: `
78+
<template>
79+
<div :class="{
80+
'hidden': !foo ? true : false,
81+
'visible': bar
82+
}" />
83+
</template>
84+
`,
85+
errors: [
86+
{
87+
message: 'Unexpected negated condition.',
88+
line: 4,
89+
column: 21,
90+
endLine: 4,
91+
endColumn: 40
92+
}
93+
]
94+
},
95+
{
96+
filename: 'test.vue',
97+
code: `
98+
<template>
99+
<div :disabled="!enabled ? true : false" />
100+
</template>
101+
`,
102+
errors: [
103+
{
104+
message: 'Unexpected negated condition.',
105+
line: 3,
106+
column: 25,
107+
endLine: 3,
108+
endColumn: 48
109+
}
110+
]
111+
},
112+
{
113+
filename: 'test.vue',
114+
code: `
115+
<template>
116+
<div :class="a !== b ? 'different' : 'same'" />
117+
</template>
118+
`,
119+
errors: [
120+
{
121+
message: 'Unexpected negated condition.',
122+
line: 3,
123+
column: 22,
124+
endLine: 3,
125+
endColumn: 52
126+
}
127+
]
128+
},
129+
{
130+
filename: 'test.vue',
131+
code: `
132+
<template>
133+
<div :class="a != b ? 'not-equal' : 'equal'" />
134+
</template>
135+
`,
136+
errors: [
137+
{
138+
message: 'Unexpected negated condition.',
139+
line: 3,
140+
column: 22,
141+
endLine: 3,
142+
endColumn: 52
143+
}
144+
]
145+
},
146+
{
147+
filename: 'test.vue',
148+
code: `
149+
<template>
150+
<div :style="{
151+
opacity: !(x && y) ? 0 : 1
152+
}" />
153+
</template>
154+
`,
155+
errors: [
156+
{
157+
message: 'Unexpected negated condition.',
158+
line: 4,
159+
column: 20,
160+
endLine: 4,
161+
endColumn: 37
162+
}
163+
]
164+
}
165+
]
166+
})

0 commit comments

Comments
 (0)