Skip to content
Open
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
5 changes: 5 additions & 0 deletions .changeset/dark-cars-shake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'eslint-plugin-vue': minor
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't merge this yet, I'd like to release a patch version first.

---

Added `ignoreVBindObject` option to `vue/attributes-order`
22 changes: 21 additions & 1 deletion docs/rules/attributes-order.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,8 @@ Note that `v-bind="object"` syntax is considered to be the same as the next or p
"CONTENT"
],
"alphabetical": false,
"sortLineLength": false
"sortLineLength": false,
"ignoreVBindObject": false
}]
}
```
Expand Down Expand Up @@ -275,6 +276,25 @@ When `alphabetical` and `sortLineLength` are both set to `true`, attributes with

</eslint-code-block>

### `"ignoreVBindObject": true`

When set to `true`, the `v-bind="object"` directive will be excluded from the attribute order check. This is useful when the spread binding is intentionally placed in a specific position for functional reasons, such as controlling the execution order of event handlers.

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

```vue
<template>
<!-- ✓ GOOD -->
<MyButton
:foo="foo"
@click="onClick"
v-bind="attrs"
/>
</template>
```

</eslint-code-block>

### Custom orders

#### `['LIST_RENDERING', 'CONDITIONALS', 'RENDER_MODIFIERS', 'GLOBAL', 'UNIQUE', 'TWO_WAY_BINDING', 'DEFINITION', 'OTHER_DIRECTIVES', 'OTHER_ATTR', 'EVENTS', 'CONTENT']`
Expand Down
21 changes: 15 additions & 6 deletions lib/rules/attributes-order.js
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,9 @@ function create(context) {
const sortLineLength = Boolean(
context.options[0] && context.options[0].sortLineLength
)
const ignoreVBindObject = Boolean(
context.options[0] && context.options[0].ignoreVBindObject
)

/** @type { { [key: string]: number } } */
const attributePosition = {}
Expand Down Expand Up @@ -383,15 +386,20 @@ function create(context) {
*/
function getAttributeAndPositionList(node) {
const attributes = node.attributes.filter((node, index, attributes) => {
// If ignoreVBindObject is enabled, ignore v-bind="object"
if (ignoreVBindObject && isVBindObject(node)) {
return false
}

// In Vue 3, ignore `v-bind="object"`, which is
// a pair of `v-bind:foo="..."` and `v-bind="object"` and
// a pair of `v-model="..."` and `v-bind="object"`,
// because changing the order behaves differently.
if (
isVBindObject(node) &&
(isVAttributeOrVBindOrVModel(attributes[index - 1]) ||
isVAttributeOrVBindOrVModel(attributes[index + 1]))
) {
// In Vue 3, ignore `v-bind="object"`, which is
// a pair of `v-bind:foo="..."` and `v-bind="object"` and
// a pair of `v-model="..."` and `v-bind="object"`,
// because changing the order behaves differently.
return false
}
return true
Expand All @@ -416,7 +424,7 @@ function create(context) {
function getPositionFromAttrIndex(index) {
const node = attributes[index]
if (isVBindObject(node)) {
// node is `v-bind ="object"` syntax
// node is `v-bind="object"` syntax

// In Vue 3, if change the order of `v-bind:foo="..."`, `v-model="..."` and `v-bind="object"`,
// the behavior will be different, so adjust so that there is no change in behavior.
Expand Down Expand Up @@ -468,7 +476,8 @@ module.exports = {
additionalItems: false
},
alphabetical: { type: 'boolean' },
sortLineLength: { type: 'boolean' }
sortLineLength: { type: 'boolean' },
ignoreVBindObject: { type: 'boolean' }
},
additionalProperties: false
}
Expand Down
79 changes: 79 additions & 0 deletions tests/lib/rules/attributes-order.js
Original file line number Diff line number Diff line change
Expand Up @@ -682,6 +682,31 @@ tester.run('attributes-order', rule, {
></div>
</template>`,
options: [{ sortLineLength: true, alphabetical: true }]
},

// ignoreVBindObject
{
filename: 'test.vue',
code: `
<template>
<div
@click="handleClick"
v-bind="attrs"
></div>
</template>`,
options: [{ ignoreVBindObject: true }]
},
{
filename: 'test.vue',
code: `
<template>
<div
ref="ref"
@click="handleClick"
v-bind="attrs"
@input="handleInput"/>
</template>`,
options: [{ ignoreVBindObject: true }]
}
],

Expand Down Expand Up @@ -2140,6 +2165,60 @@ tester.run('attributes-order', rule, {
}
]
},
{
filename: 'test.vue',
code: `
<template>
<div
@click="handleClick"
v-bind="attrs"
></div>
</template>`,
output: `
<template>
<div
v-bind="attrs"
@click="handleClick"
></div>
</template>`,
errors: [
{
message: 'Attribute "v-bind" should go before "@click".',
line: 5,
column: 11,
endLine: 5,
endColumn: 25
}
]
},
{
filename: 'test.vue',
code: `
<template>
<div
ref="ref"
@click="handleClick"
v-bind="attrs"
></div>
</template>`,
output: `
<template>
<div
ref="ref"
v-bind="attrs"
@click="handleClick"
></div>
</template>`,
errors: [
{
message: 'Attribute "v-bind" should go before "@click".',
line: 6,
column: 11,
endLine: 6,
endColumn: 25
}
]
},
{
filename: 'test.vue',
code: `
Expand Down
Loading