Skip to content

Commit

Permalink
feat(RFC0011): add vue/no-custom-modifiers-on-v-model rule which chec…
Browse files Browse the repository at this point in the history
…ks if v-model has not allowed modifiers (Vue 2 backward compatibility)
  • Loading branch information
przemkow committed Jan 26, 2020
1 parent 1955fb5 commit 900f89e
Show file tree
Hide file tree
Showing 6 changed files with 185 additions and 0 deletions.
1 change: 1 addition & 0 deletions docs/rules/README.md
Expand Up @@ -39,6 +39,7 @@ Enforce all the rules in this category, as well as all higher priority rules, wi
| Rule ID | Description | |
|:--------|:------------|:---|
| [vue/no-async-in-computed-properties](./no-async-in-computed-properties.md) | disallow asynchronous actions in computed properties | |
| [vue/no-custom-modifiers-on-v-model](./no-custom-modifiers-on-v-model.md) | disallow custom modifiers on v-model used on the component | |
| [vue/no-dupe-keys](./no-dupe-keys.md) | disallow duplication of field names | |
| [vue/no-duplicate-attributes](./no-duplicate-attributes.md) | disallow duplication of attributes | |
| [vue/no-parsing-error](./no-parsing-error.md) | disallow parsing errors in `<template>` | |
Expand Down
53 changes: 53 additions & 0 deletions docs/rules/no-custom-modifiers-on-v-model.md
@@ -0,0 +1,53 @@
---
pageClass: rule-details
sidebarDepth: 0
title: vue/no-custom-modifiers-on-v-model
description: disallow custom modifiers on v-model used on the component
---
# vue/no-custom-modifiers-on-v-model
> disallow custom modifiers on v-model used on the component
- :gear: This rule is included in all of `"plugin:vue/essential"`, `"plugin:vue/strongly-recommended"` and `"plugin:vue/recommended"`.

This rule checks whether `v-model `used on the component do not have custom modifiers.

## Rule Details

This rule reports `v-model` directives in the following cases:

- The directive used on the component has custom modifiers. E.g. `<MyComponent v-model.aaa="foo" />`

<eslint-code-block :rules="{'vue/no-custom-modifiers-on-v-model': ['error']}">

```vue
<template>
<!-- ✓ GOOD -->
<MyComponent v-model="foo" />
<MyComponent v-model.trim="foo" />
<MyComponent v-model.lazy="foo" />
<MyComponent v-model.number="foo" />
<!-- ✗ BAD -->
<MyComponent v-model.aaa="foo" />
<MyComponent v-model.aaa.bbb="foo" />
</template>
```

</eslint-code-block>

### Options

Nothing.

## :couple: Related rules

- [valid-v-model]

[valid-v-model]: valid-v-model.md

## :mag: Implementation

- [Rule source](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/no-custom-modifiers-on-v-model.js)
- [Test source](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/no-custom-modifiers-on-v-model.js)
1 change: 1 addition & 0 deletions lib/configs/essential.js
Expand Up @@ -7,6 +7,7 @@ module.exports = {
extends: require.resolve('./base'),
rules: {
'vue/no-async-in-computed-properties': 'error',
'vue/no-custom-modifiers-on-v-model': 'error',
'vue/no-dupe-keys': 'error',
'vue/no-duplicate-attributes': 'error',
'vue/no-parsing-error': 'error',
Expand Down
1 change: 1 addition & 0 deletions lib/index.js
Expand Up @@ -39,6 +39,7 @@ module.exports = {
'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-custom-modifiers-on-v-model': require('./rules/no-custom-modifiers-on-v-model'),
'no-deprecated-scope-attribute': require('./rules/no-deprecated-scope-attribute'),
'no-deprecated-slot-attribute': require('./rules/no-deprecated-slot-attribute'),
'no-deprecated-slot-scope-attribute': require('./rules/no-deprecated-slot-scope-attribute'),
Expand Down
57 changes: 57 additions & 0 deletions lib/rules/no-custom-modifiers-on-v-model.js
@@ -0,0 +1,57 @@
/**
* @author Przemyslaw Falowski (@przemkow)
* @fileoverview This rule checks whether v-model used on the component do not have custom modifiers
*/
'use strict'

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

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

// ------------------------------------------------------------------------------
// Helpers
// ------------------------------------------------------------------------------

const VALID_MODIFIERS = new Set(['lazy', 'number', 'trim'])

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

module.exports = {
meta: {
type: 'problem',
docs: {
description: 'disallow custom modifiers on v-model used on the component',
category: 'essential',
url: 'https://eslint.vuejs.org/rules/no-custom-modifiers-on-v-model.html'
},
fixable: null,
schema: [],
messages: {
notSupportedModifier: "'v-model' directives don't support the modifier '{{name}}'."
}
},
create (context) {
return utils.defineTemplateBodyVisitor(context, {
"VAttribute[directive=true][key.name.name='model']" (node) {
const element = node.parent.parent

if (utils.isCustomComponent(element)) {
for (const modifier of node.key.modifiers) {
if (!VALID_MODIFIERS.has(modifier.name)) {
context.report({
node,
loc: node.loc,
messageId: 'notSupportedModifier',
data: { name: modifier.name }
})
}
}
}
}
})
}
}
72 changes: 72 additions & 0 deletions tests/lib/rules/no-custom-modifiers-on-v-model.js
@@ -0,0 +1,72 @@
/**
* @author Przemyslaw Falowski (@przemkow)
* @fileoverview This rule checks whether v-model used on the component do not have custom modifiers
*/
'use strict'

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

const rule = require('../../../lib/rules/no-custom-modifiers-on-v-model')
const RuleTester = require('eslint').RuleTester

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

const ruleTester = new RuleTester({
parser: require.resolve('vue-eslint-parser'),
parserOptions: { ecmaVersion: 2015 }
})

ruleTester.run('no-custom-modifiers-on-v-model', rule, {

valid: [
{
filename: 'test.vue',
code: '<template><MyComponent v-model:propName="foo"></template>'
},
{
filename: 'test.vue',
code: '<template><MyComponent v-model="foo"></template>'
},
{
filename: 'test.vue',
code: '<template><MyComponent v-model:propName.trim="foo"></template>'
},
{
filename: 'test.vue',
code: '<template><MyComponent v-model.trim="foo"></template>'
},
{
filename: 'test.vue',
code: '<template><MyComponent v-model:propName.lazy="foo"></template>'
},
{
filename: 'test.vue',
code: '<template><MyComponent v-model.lazy="foo"></template>'
},
{
filename: 'test.vue',
code: '<template><MyComponent v-model:propName.number="foo"></template>'
},
{
filename: 'test.vue',
code: '<template><MyComponent v-model.number="foo"></template>'
}
],

invalid: [
{
filename: 'test.vue',
code: '<template><MyComponent v-model:propName.aaa="foo"></template>',
errors: ["'v-model' directives don't support the modifier 'aaa'."]
},
{
filename: 'test.vue',
code: '<template><MyComponent v-model.aaa="foo"></template>',
errors: ["'v-model' directives don't support the modifier 'aaa'."]
}
]
})

0 comments on commit 900f89e

Please sign in to comment.