Skip to content

Fixed false positives for binded and unbinded attrs in 'vue/attributes-order' with alphabetical option. #1055

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Feb 17, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions docs/rules/attributes-order.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,12 +106,13 @@ This rule aims to enforce ordering of component attributes. The default order is
"EVENTS",
"CONTENT"
],
"alphabetical": true
"alphabetical": false
}]
}
```

### Alphabetical order
### `"alphabetical": true`

<eslint-code-block fix :rules="{'vue/attributes-order': ['error', {alphabetical: true}]}">

```vue
Expand All @@ -122,6 +123,8 @@ This rule aims to enforce ordering of component attributes. The default order is
:another-custom-prop="value"
:blue-color="false"
boolean-prop
class="foo"
:class="bar"
z-prop="Z"
v-on:[c]="functionCall"
@change="functionCall"
Expand All @@ -147,8 +150,13 @@ This rule aims to enforce ordering of component attributes. The default order is
</div>

<div
:a-prop="A"
:z-prop="Z">
:z-prop="Z"
:a-prop="A">
</div>

<div
:class="foo"
class="bar">
</div>

</template>
Expand Down
23 changes: 20 additions & 3 deletions lib/rules/attributes-order.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,20 @@ const ATTRS = {

function getAttributeName (attribute, sourceCode) {
const isBind = attribute.directive && attribute.key.name.name === 'bind'
debugger
return isBind
? (attribute.key.argument ? sourceCode.getText(attribute.key.argument) : '')
: (attribute.directive ? sourceCode.getText(attribute.key.argument) : attribute.key.name)
: (attribute.directive ? getDirectiveKeyName(attribute.key, sourceCode) : attribute.key.name)
}

function getDirectiveKeyName (directiveKey, sourceCode) {
let text = 'v-' + directiveKey.name.name
if (directiveKey.argument) {
text += ':' + sourceCode.getText(directiveKey.argument)
}
for (const modifier of directiveKey.modifiers) {
text += '.' + modifier.name
}
return text
}

function getAttributeType (attribute, sourceCode) {
Expand Down Expand Up @@ -75,7 +85,14 @@ function getPosition (attribute, attributePosition, sourceCode) {
function isAlphabetical (prevNode, currNode, sourceCode) {
const isSameType = getAttributeType(prevNode, sourceCode) === getAttributeType(currNode, sourceCode)
if (isSameType) {
return getAttributeName(prevNode, sourceCode) < getAttributeName(currNode, sourceCode)
const prevName = getAttributeName(prevNode, sourceCode)
const currName = getAttributeName(currNode, sourceCode)
if (prevName === currName) {
const prevIsBind = Boolean(prevNode.directive && prevNode.key.name.name === 'bind')
const currIsBind = Boolean(currNode.directive && currNode.key.name.name === 'bind')
return prevIsBind <= currIsBind
}
return prevName < currName
}
return true
}
Expand Down
150 changes: 150 additions & 0 deletions tests/lib/rules/attributes-order.js
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,72 @@ tester.run('attributes-order', rule, {
</div>
</template>`,
options: [{ alphabetical: true }]
},
{
filename: 'test.vue',
code:
`<template>
<div
class="foo"
:class="bar">
</div>
</template>`,
options: [{ alphabetical: true }]
},
{
filename: 'duplicate.vue',
code:
`<template>
<div
class="foo"
class="bar">
</div>
</template>`,
options: [{ alphabetical: true }]
},
{
filename: 'duplicate.vue',
code:
`<template>
<div
:class="foo"
:class="bar">
</div>
</template>`,
options: [{ alphabetical: true }]
},
{
filename: 'test.vue',
code:
`<template>
<div
v-if="foo"
v-show="bar">
</div>
</template>`,
options: [{ alphabetical: true }]
},
{
filename: 'test.vue',
code:
`<template>
<div
v-bar="bar"
v-foo="foo">
</div>
</template>`,
options: [{ alphabetical: true }]
},
{
filename: 'test.vue',
code:
`<template>
<div
v-foo.a="a"
v-foo.b="b">
</div>
</template>`,
options: [{ alphabetical: true }]
}
],

Expand Down Expand Up @@ -778,6 +844,90 @@ tester.run('attributes-order', rule, {
message: 'Attribute "v-on:click" should go before "v-text".',
type: 'VDirectiveKey'
}]
},
{
filename: 'test.vue',
code:
`<template>
<div
:class="foo"
class="bar">
</div>
</template>`,
options: [{ alphabetical: true }],
output:
`<template>
<div
class="bar"
:class="foo">
</div>
</template>`,
errors: [{
message: 'Attribute "class" should go before ":class".'
}]
},
{
filename: 'test.vue',
code:
`<template>
<div
v-show="foo"
v-if="bar">
</div>
</template>`,
options: [{ alphabetical: true }],
output:
`<template>
<div
v-if="bar"
v-show="foo">
</div>
</template>`,
errors: [{
message: 'Attribute "v-if" should go before "v-show".'
}]
},
{
filename: 'test.vue',
code:
`<template>
<div
v-foo="foo"
v-bar="bar">
</div>
</template>`,
options: [{ alphabetical: true }],
output:
`<template>
<div
v-bar="bar"
v-foo="foo">
</div>
</template>`,
errors: [{
message: 'Attribute "v-bar" should go before "v-foo".'
}]
},
{
filename: 'test.vue',
code:
`<template>
<div
v-foo.b="b"
v-foo.a="a">
</div>
</template>`,
options: [{ alphabetical: true }],
output:
`<template>
<div
v-foo.a="a"
v-foo.b="b">
</div>
</template>`,
errors: [{
message: 'Attribute "v-foo.a" should go before "v-foo.b".'
}]
}
]
})