-
-
Notifications
You must be signed in to change notification settings - Fork 664
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add
vue/no-invalid-attribute-name
rule (#1851)
* Fix #1373: Add rule no-invalid-attribute-name * Remove stray newline * Apply suggestions from code review Co-authored-by: Flo Edelmann <[email protected]> * #1373 Use xml-name-validator * Fix linting error * remove stray newline * refactor test code * Update lib/rules/no-invalid-attribute-name.js Co-authored-by: Flo Edelmann <[email protected]> * fix bad commit from github ui * fix typechecking error * Respond to PR feedback * Include the added types in package.json * check v-bind directives * Update tests/lib/rules/no-invalid-attribute-name.js Co-authored-by: Flo Edelmann <[email protected]> * Fix failing unit test * Update lib/rules/no-invalid-attribute-name.js * Update lib/rules/no-invalid-attribute-name.js * Update tests/lib/rules/no-invalid-attribute-name.js * Update tests/lib/rules/no-invalid-attribute-name.js Co-authored-by: Flo Edelmann <[email protected]> Co-authored-by: Yosuke Ota <[email protected]>
- Loading branch information
1 parent
b0639d7
commit ab85fd6
Showing
6 changed files
with
263 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
--- | ||
pageClass: rule-details | ||
sidebarDepth: 0 | ||
title: vue/no-invalid-attribute-name | ||
description: require valid attribute names | ||
--- | ||
# vue/no-invalid-attribute-name | ||
|
||
> require valid attribute names | ||
- :exclamation: <badge text="This rule has not been released yet." vertical="middle" type="error"> ***This rule has not been released yet.*** </badge> | ||
|
||
## :book: Rule Details | ||
|
||
This rule detects invalid HTML attributes. | ||
|
||
<eslint-code-block :rules="{'vue/no-invalid-attribute-name': ['error']}"> | ||
|
||
```vue | ||
<template> | ||
<!-- ✓ GOOD --> | ||
<p foo.bar></p> | ||
<p foo-bar></p> | ||
<p _foo.bar></p> | ||
<p :foo-bar></p> | ||
<!-- ✗ BAD --> | ||
<p 0abc></p> | ||
<p -def></p> | ||
<p !ghi></p> | ||
</template> | ||
``` | ||
|
||
</eslint-code-block> | ||
|
||
## :wrench: Options | ||
|
||
Nothing. | ||
|
||
## :mag: Implementation | ||
|
||
- [Rule source](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/no-invalid-attribute-name.js) | ||
- [Test source](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/no-invalid-attribute-name.js) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
/** | ||
* @author Doug Wade <[email protected]> | ||
* See LICENSE file in root directory for full license. | ||
*/ | ||
'use strict' | ||
|
||
const utils = require('../utils') | ||
const xnv = require('xml-name-validator') | ||
|
||
module.exports = { | ||
meta: { | ||
type: 'problem', | ||
docs: { | ||
description: 'require valid attribute names', | ||
categories: undefined, | ||
url: 'https://eslint.vuejs.org/rules/no-invalid-attribute-name.html' | ||
}, | ||
fixable: null, | ||
schema: [], | ||
messages: { | ||
attribute: 'Attribute name {{name}} is not valid.' | ||
} | ||
}, | ||
/** @param {RuleContext} context */ | ||
create(context) { | ||
/** | ||
* @param {string | VIdentifier} key | ||
* @return {string} | ||
*/ | ||
const getName = (key) => (typeof key === 'string' ? key : key.name) | ||
|
||
return utils.defineTemplateBodyVisitor(context, { | ||
/** @param {VDirective | VAttribute} node */ | ||
VAttribute(node) { | ||
if (utils.isCustomComponent(node.parent.parent)) { | ||
return | ||
} | ||
|
||
const name = getName(node.key.name) | ||
|
||
if ( | ||
node.directive && | ||
name === 'bind' && | ||
node.key.argument && | ||
node.key.argument.type === 'VIdentifier' && | ||
!xnv.name(node.key.argument.name) | ||
) { | ||
context.report({ | ||
node, | ||
messageId: 'attribute', | ||
data: { | ||
name: node.key.argument.name | ||
} | ||
}) | ||
} | ||
|
||
if (!node.directive && !xnv.name(name)) { | ||
context.report({ | ||
node, | ||
messageId: 'attribute', | ||
data: { | ||
name | ||
} | ||
}) | ||
} | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
/** | ||
* @author *****your name***** | ||
* See LICENSE file in root directory for full license. | ||
*/ | ||
'use strict' | ||
|
||
const RuleTester = require('eslint').RuleTester | ||
const rule = require('../../../lib/rules/no-invalid-attribute-name') | ||
|
||
const tester = new RuleTester({ | ||
parser: require.resolve('vue-eslint-parser'), | ||
parserOptions: { | ||
ecmaVersion: 2020, | ||
sourceType: 'module' | ||
} | ||
}) | ||
|
||
tester.run('no-invalid-attribute-name', rule, { | ||
valid: [ | ||
{ | ||
filename: 'test.vue', | ||
code: '<template><p foo /></template>' | ||
}, | ||
{ | ||
filename: 'test.vue', | ||
code: `<template><p foo="bar" /></template>` | ||
}, | ||
{ | ||
filename: 'test.vue', | ||
code: `<template><p foo-bar /></template>` | ||
}, | ||
{ | ||
filename: 'test.vue', | ||
code: `<template><p _foo-bar /></template>` | ||
}, | ||
{ | ||
filename: 'test.vue', | ||
code: `<template><p :foo-bar /></template>` | ||
}, | ||
{ | ||
filename: 'test.vue', | ||
code: `<template><p foo.bar /></template>` | ||
}, | ||
{ | ||
filename: 'test.vue', | ||
code: `<template><p quux-.9 /></template>` | ||
}, | ||
{ | ||
filename: 'test.vue', | ||
code: `<template><MyComponent 0abc="foo" /></template>` | ||
}, | ||
{ | ||
filename: 'test.vue', | ||
code: `<template><MyComponent :0abc="foo" /></template>` | ||
}, | ||
{ | ||
filename: 'test.vue', | ||
code: `<template><a :href="url"> ... </a></template>` | ||
}, | ||
{ | ||
filename: 'test.vue', | ||
code: `<template><div v-bind:class="{ active: isActive }"></div></template>` | ||
}, | ||
{ | ||
filename: 'test.vue', | ||
code: `<template><p v-if="seen">Now you see me</p></template>` | ||
}, | ||
{ | ||
filename: 'test.vue', | ||
code: `<a v-on:[eventName]="doSomething"> ... </a>` | ||
}, | ||
{ | ||
filename: 'test.vue', | ||
code: `<form v-on:submit.prevent="onSubmit"> ... </form>` | ||
}, | ||
{ | ||
filename: 'test.vue', | ||
code: `<a @[event]="doSomething"> ... </a>` | ||
}, | ||
{ | ||
filename: 'test.vue', | ||
code: `<template><div v-bind="..."></div></template>` | ||
}, | ||
{ | ||
filename: 'test.vue', | ||
code: `<template><div v-0abc="..."></div></template>` | ||
} | ||
], | ||
invalid: [ | ||
{ | ||
filename: 'test.vue', | ||
code: `<template><p 0abc /></template>`, | ||
errors: [ | ||
{ | ||
message: 'Attribute name 0abc is not valid.', | ||
line: 1, | ||
column: 14 | ||
} | ||
] | ||
}, | ||
{ | ||
filename: 'test.vue', | ||
code: `<template><p -def></template>`, | ||
errors: [ | ||
{ | ||
message: 'Attribute name -def is not valid.', | ||
line: 1, | ||
column: 14 | ||
} | ||
] | ||
}, | ||
{ | ||
filename: 'test.vue', | ||
code: `<template><p !ghi /></template>`, | ||
errors: [ | ||
{ | ||
message: 'Attribute name !ghi is not valid.', | ||
line: 1, | ||
column: 14 | ||
} | ||
] | ||
}, | ||
{ | ||
filename: 'test.vue', | ||
code: `<template><p v-bind:0abc=""></template>`, | ||
errors: [ | ||
{ | ||
message: 'Attribute name 0abc is not valid.', | ||
line: 1, | ||
column: 14 | ||
} | ||
] | ||
}, | ||
{ | ||
filename: 'test.vue', | ||
code: `<template><p :0abc="..." /></template>`, | ||
errors: [ | ||
{ | ||
message: 'Attribute name 0abc is not valid.', | ||
line: 1, | ||
column: 14 | ||
} | ||
] | ||
} | ||
] | ||
}) |