Skip to content
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

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

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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 12 additions & 4 deletions docs/rules/attributes-order.md
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
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
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".'
}]
}
]
})