Navigation Menu

Skip to content

Commit

Permalink
⭐️New: Add rule no-boolean-default (#612)
Browse files Browse the repository at this point in the history
* no-boolean-default

* Rule files

* PR changes

* Added docs

* Added more tests

* Update implementation

* Update config and docs
  • Loading branch information
privatenumber authored and michalsnik committed Feb 3, 2019
1 parent ae03c28 commit 617139e
Show file tree
Hide file tree
Showing 5 changed files with 306 additions and 0 deletions.
1 change: 1 addition & 0 deletions docs/rules/README.md
Expand Up @@ -149,6 +149,7 @@ For example:
| [vue/eqeqeq](./eqeqeq.md) | require the use of `===` and `!==` | :wrench: |
| [vue/key-spacing](./key-spacing.md) | enforce consistent spacing between keys and values in object literal properties | :wrench: |
| [vue/match-component-file-name](./match-component-file-name.md) | require component name property to match its file name | |
| [vue/no-boolean-default](./no-boolean-default.md) | disallow boolean defaults | :wrench: |
| [vue/no-restricted-syntax](./no-restricted-syntax.md) | disallow specified syntax | |
| [vue/object-curly-spacing](./object-curly-spacing.md) | enforce consistent spacing inside braces | :wrench: |
| [vue/require-direct-export](./require-direct-export.md) | require the component to be directly exported | |
Expand Down
49 changes: 49 additions & 0 deletions docs/rules/no-boolean-default.md
@@ -0,0 +1,49 @@
---
pageClass: rule-details
sidebarDepth: 0
title: vue/no-boolean-default
description: disallow boolean defaults
---
# vue/no-boolean-default
> disallow boolean defaults
- :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.

The rule prevents Boolean props from having a default value.


## :book: Rule Details
The rule is to enforce the HTML standard of always defaulting boolean attributes to false.

<eslint-code-block fix :rules="{'vue/no-boolean-default': ['error']}">

```vue
<script>
export default {
props: {
foo: {
type: Boolean,
default: true
},
bar: {
type: Boolean
}
}
}
</script>
```

</eslint-code-block>

## :wrench: Options
- `'no-default'` (default) allows a prop definition object, but enforces that the `default` property not be defined.
- `'default-false'` enforces that the default can be set but must be set to `false`.

```json
"vue/no-boolean-default": ["error", "no-default|default-false"]
```

## :mag: Implementation

- [Rule source](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/no-boolean-default.js)
- [Test source](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/no-boolean-default.js)
1 change: 1 addition & 0 deletions lib/index.js
Expand Up @@ -32,6 +32,7 @@ module.exports = {
'mustache-interpolation-spacing': require('./rules/mustache-interpolation-spacing'),
'name-property-casing': require('./rules/name-property-casing'),
'no-async-in-computed-properties': require('./rules/no-async-in-computed-properties'),
'no-boolean-default': require('./rules/no-boolean-default'),
'no-confusing-v-for-v-if': require('./rules/no-confusing-v-for-v-if'),
'no-dupe-keys': require('./rules/no-dupe-keys'),
'no-duplicate-attributes': require('./rules/no-duplicate-attributes'),
Expand Down
92 changes: 92 additions & 0 deletions lib/rules/no-boolean-default.js
@@ -0,0 +1,92 @@
/**
* @fileoverview Prevents boolean defaults from being set
* @author Hiroki Osame
*/
'use strict'

const utils = require('../utils')

// ------------------------------------------------------------------------------
// Rule Definition
// ------------------------------------------------------------------------------

function isBooleanProp (prop) {
return (
prop.type === 'Property' &&
prop.key.type === 'Identifier' &&
prop.key.name === 'type' &&
prop.value.type === 'Identifier' &&
prop.value.name === 'Boolean'
)
}

function getBooleanProps (props) {
return props
.filter(prop => (
prop.value &&
prop.value.properties &&
prop.value.properties.find(isBooleanProp)
))
}

function getDefaultNode (propDef) {
return propDef.value.properties.find(p => {
return (
p.type === 'Property' &&
p.key.type === 'Identifier' &&
p.key.name === 'default'
)
})
}

module.exports = {
meta: {
type: 'suggestion',
docs: {
description: 'disallow boolean defaults',
category: undefined,
url: 'https://eslint.vuejs.org/rules/no-boolean-default.html'
},
fixable: 'code',
schema: [
{
enum: ['default-false', 'no-default']
}
]
},

create (context) {
return utils.executeOnVueComponent(context, (obj) => {
const props = utils.getComponentProps(obj)
const booleanProps = getBooleanProps(props)

if (!booleanProps.length) return

const booleanType = context.options[0] || 'no-default'

booleanProps.forEach((propDef) => {
const defaultNode = getDefaultNode(propDef)

switch (booleanType) {
case 'no-default':
if (defaultNode) {
context.report({
node: defaultNode,
message: 'Boolean prop should not set a default (Vue defaults it to false).'
})
}
break

case 'default-false':
if (defaultNode.value.value !== false) {
context.report({
node: defaultNode,
message: 'Boolean prop should be defaulted to false.'
})
}
break
}
})
})
}
}
163 changes: 163 additions & 0 deletions tests/lib/rules/no-boolean-default.js
@@ -0,0 +1,163 @@
/**
* @fileoverview Prevents boolean defaults from being set
* @author Hiroki Osame
*/
'use strict'

// ------------------------------------------------------------------------------
// Requirements
// ------------------------------------------------------------------------------

var rule = require('../../../lib/rules/no-boolean-default')

var RuleTester = require('eslint').RuleTester

// ------------------------------------------------------------------------------
// Tests
// ------------------------------------------------------------------------------

var ruleTester = new RuleTester({
parserOptions: {
ecmaVersion: 2018,
sourceType: 'module'
}
})
ruleTester.run('no-boolean-default', rule, {

valid: [
{
filename: 'test.vue',
code: `
export default {
props: {
enabled: Boolean
}
}
`
},
{
filename: 'test.vue',
code: `
const props = {};
export default {
props: {
...props,
enabled: Boolean
}
}
`
},
{
filename: 'test.vue',
code: `
const data = {};
export default {
props: {
enabled: {
type: Boolean,
...data
}
}
}
`,
options: ['no-default']
},
{
filename: 'test.vue',
code: `
const data = {};
export default {
props: {
enabled: {
type: Boolean,
default: false,
...data
}
}
}
`,
options: ['default-false']
},
{
filename: 'test.vue',
code: `
const data = {};
export default {
props: {
enabled: data
}
}
`
},
{
filename: 'test.vue',
code: `
const data = {};
export default {
props: {
enabled: {
...data
}
}
}
`
}
],

invalid: [
{
filename: 'test.vue',
code: `
export default {
props: {
enabled: {
type: Boolean,
default: true,
}
}
}
`,
options: ['default-false'],
errors: [{
message: 'Boolean prop should be defaulted to false.',
line: 6
}]
},
{
filename: 'test.vue',
code: `
export default {
props: {
enabled: {
type: Boolean,
default: null,
}
}
}
`,
options: ['default-false'],
errors: [{
message: 'Boolean prop should be defaulted to false.',
line: 6
}]
},
{
filename: 'test.vue',
code: `
export default {
props: {
enabled: {
type: Boolean,
default: false,
}
}
}
`,
options: ['no-default'],
errors: [{
message: 'Boolean prop should not set a default (Vue defaults it to false).',
line: 6
}]
}
]
})

0 comments on commit 617139e

Please sign in to comment.