Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit adc460d

Browse files
0xA1337waynzh
andauthored
feat(attributes-order): add sortLineLength option (#2759)
Co-authored-by: waynzh <waynzh19@gmail.com>
1 parent 10d645e commit adc460d

File tree

4 files changed

+343
-4
lines changed

4 files changed

+343
-4
lines changed

‎.changeset/social-ghosts-dress.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'eslint-plugin-vue': minor
3+
---
4+
5+
Added `sortLineLength` option to [`vue/attributes-order`](https://eslint.vuejs.org/rules/attributes-order.html)

‎docs/rules/attributes-order.md

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,8 @@ Note that `v-bind="object"` syntax is considered to be the same as the next or p
143143
"EVENTS",
144144
"CONTENT"
145145
],
146-
"alphabetical": false
146+
"alphabetical": false,
147+
"sortLineLength": false
147148
}]
148149
}
149150
```
@@ -201,6 +202,79 @@ Note that `v-bind="object"` syntax is considered to be the same as the next or p
201202

202203
</eslint-code-block>
203204

205+
### `"sortLineLength": true`
206+
207+
<eslint-code-block fix :rules="{'vue/attributes-order': ['error', {sortLineLength: true}]}">
208+
209+
```vue
210+
<template>
211+
<!-- ✓ GOOD -->
212+
<div
213+
a="short"
214+
abc="value"
215+
a-prop="longer"
216+
boolean-prop
217+
:my-prop="value"
218+
very-long-prop="value"
219+
@blur="functionCall"
220+
@change="functionCall"
221+
@input="handleInput">
222+
</div>
223+
224+
<!-- ✗ BAD -->
225+
<div
226+
very-long-prop="value"
227+
a="short"
228+
a-prop="longer">
229+
</div>
230+
231+
<div
232+
@input="handleInput"
233+
@blur="short">
234+
</div>
235+
236+
<div
237+
:my-prop="value"
238+
:a="short">
239+
</div>
240+
241+
</template>
242+
```
243+
244+
</eslint-code-block>
245+
246+
### `"alphabetical": true` with `"sortLineLength": true`
247+
248+
When `alphabetical` and `sortLineLength` are both set to `true`, attributes within the same group are sorted primarily by their line length, and then alphabetically as a tie-breaker for attributes with the same length. This provides a clean, predictable attribute order that enhances readability.
249+
250+
<eslint-code-block fix :rules="{'vue/attributes-order': ['error', {alphabetical: true, sortLineLength: true}]}">
251+
252+
```vue
253+
<template>
254+
<!-- ✓ GOOD -->
255+
<div
256+
a="1"
257+
b="2"
258+
cc="3"
259+
dd="4"
260+
@keyup="fn"
261+
@submit="fn"
262+
></div>
263+
264+
<!-- ✗ BAD -->
265+
<div
266+
b="2"
267+
a="1"
268+
@submit="fn"
269+
@keyup="fn"
270+
dd="4"
271+
cc="3"
272+
></div>
273+
</template>
274+
```
275+
276+
</eslint-code-block>
277+
204278
### Custom orders
205279

206280
#### `['LIST_RENDERING', 'CONDITIONALS', 'RENDER_MODIFIERS', 'GLOBAL', 'UNIQUE', 'TWO_WAY_BINDING', 'DEFINITION', 'OTHER_DIRECTIVES', 'OTHER_ATTR', 'EVENTS', 'CONTENT']`

‎lib/rules/attributes-order.js

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,9 @@ function create(context) {
271271
const alphabetical = Boolean(
272272
context.options[0] && context.options[0].alphabetical
273273
)
274+
const sortLineLength = Boolean(
275+
context.options[0] && context.options[0].sortLineLength
276+
)
274277

275278
/** @type { { [key: string]: number } } */
276279
const attributePosition = {}
@@ -347,9 +350,23 @@ function create(context) {
347350
const { attr, position } = attributeAndPositions[index]
348351

349352
let valid = previousPosition <= position
350-
if (valid && alphabetical && previousPosition === position) {
351-
valid = isAlphabetical(previousNode, attr, sourceCode)
353+
if (valid && previousPosition === position) {
354+
let sortedByLength = false
355+
if (sortLineLength) {
356+
const prevText = sourceCode.getText(previousNode)
357+
const currText = sourceCode.getText(attr)
358+
359+
if (prevText.length !== currText.length) {
360+
valid = prevText.length < currText.length
361+
sortedByLength = true
362+
}
363+
}
364+
365+
if (alphabetical && !sortedByLength) {
366+
valid = isAlphabetical(previousNode, attr, sourceCode)
367+
}
352368
}
369+
353370
if (valid) {
354371
previousNode = attr
355372
previousPosition = position
@@ -450,7 +467,8 @@ module.exports = {
450467
uniqueItems: true,
451468
additionalItems: false
452469
},
453-
alphabetical: { type: 'boolean' }
470+
alphabetical: { type: 'boolean' },
471+
sortLineLength: { type: 'boolean' }
454472
},
455473
additionalProperties: false
456474
}

‎tests/lib/rules/attributes-order.js

Lines changed: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -617,6 +617,71 @@ tester.run('attributes-order', rule, {
617617
alphabetical: false
618618
}
619619
]
620+
},
621+
{
622+
filename: 'test.vue',
623+
code: `
624+
<template>
625+
<div
626+
short="val"
627+
medium-attr="value"
628+
very-long-attribute-name="value">
629+
</div>
630+
</template>`,
631+
options: [{ sortLineLength: true }]
632+
},
633+
{
634+
filename: 'test.vue',
635+
code: `
636+
<template>
637+
<div
638+
v-if="condition"
639+
v-show="show"
640+
short="val"
641+
medium-attr="value"
642+
very-long-attribute-name="value">
643+
</div>
644+
</template>`,
645+
options: [{ sortLineLength: false }]
646+
},
647+
{
648+
filename: 'test.vue',
649+
code: `
650+
<template>
651+
<div
652+
@click="fn"
653+
@input="handleInput"
654+
@mouseover="handleMouseover">
655+
</div>
656+
</template>`,
657+
options: [{ sortLineLength: true }]
658+
},
659+
{
660+
filename: 'test.vue',
661+
code: `
662+
<template>
663+
<div
664+
:a="value"
665+
:ab="value"
666+
:abc="value">
667+
</div>
668+
</template>`,
669+
options: [{ sortLineLength: true }]
670+
},
671+
{
672+
filename: 'test.vue',
673+
code: `
674+
<template>
675+
<div
676+
bb="v"
677+
zz="v"
678+
aaa="v"
679+
@click="fn"
680+
@keyup="fn"
681+
@submit="fn"
682+
></div>
683+
</template>`,
684+
options: [{ sortLineLength: true, alphabetical: true }]
620685
}
621686
],
622687

@@ -2102,6 +2167,183 @@ tester.run('attributes-order', rule, {
21022167
endColumn: 26
21032168
}
21042169
]
2170+
},
2171+
{
2172+
filename: 'test.vue',
2173+
code: `
2174+
<template>
2175+
<div
2176+
medium-attr="value"
2177+
short="val"
2178+
very-long-attribute-name="value">
2179+
</div>
2180+
</template>`,
2181+
output: `
2182+
<template>
2183+
<div
2184+
short="val"
2185+
medium-attr="value"
2186+
very-long-attribute-name="value">
2187+
</div>
2188+
</template>`,
2189+
options: [{ sortLineLength: true }],
2190+
errors: ['Attribute "short" should go before "medium-attr".']
2191+
},
2192+
{
2193+
filename: 'test.vue',
2194+
code: `
2195+
<template>
2196+
<div
2197+
very-long-attribute-name="value"
2198+
short="val">
2199+
</div>
2200+
</template>`,
2201+
output: `
2202+
<template>
2203+
<div
2204+
short="val"
2205+
very-long-attribute-name="value">
2206+
</div>
2207+
</template>`,
2208+
options: [{ sortLineLength: true }],
2209+
errors: ['Attribute "short" should go before "very-long-attribute-name".']
2210+
},
2211+
{
2212+
filename: 'test.vue',
2213+
code: `
2214+
<template>
2215+
<div
2216+
id="id"
2217+
v-model="foo"
2218+
very-long-attribute-name="value"
2219+
short="val">
2220+
</div>
2221+
</template>`,
2222+
output: `
2223+
<template>
2224+
<div
2225+
id="id"
2226+
v-model="foo"
2227+
short="val"
2228+
very-long-attribute-name="value">
2229+
</div>
2230+
</template>`,
2231+
options: [{ sortLineLength: true }],
2232+
errors: ['Attribute "short" should go before "very-long-attribute-name".']
2233+
},
2234+
{
2235+
filename: 'test.vue',
2236+
code: `
2237+
<template>
2238+
<div
2239+
@mouseover="handleMouseover"
2240+
@click="fn"
2241+
@input="handleInput">
2242+
</div>
2243+
</template>`,
2244+
output: `
2245+
<template>
2246+
<div
2247+
@click="fn"
2248+
@mouseover="handleMouseover"
2249+
@input="handleInput">
2250+
</div>
2251+
</template>`,
2252+
options: [{ sortLineLength: true }],
2253+
errors: [
2254+
'Attribute "@click" should go before "@mouseover".',
2255+
'Attribute "@input" should go before "@mouseover".'
2256+
]
2257+
},
2258+
{
2259+
filename: 'test.vue',
2260+
code: `
2261+
<template>
2262+
<div
2263+
:abc="value"
2264+
:a="value"
2265+
:ab="value">
2266+
</div>
2267+
</template>`,
2268+
output: `
2269+
<template>
2270+
<div
2271+
:a="value"
2272+
:abc="value"
2273+
:ab="value">
2274+
</div>
2275+
</template>`,
2276+
options: [{ sortLineLength: true }],
2277+
errors: [
2278+
'Attribute ":a" should go before ":abc".',
2279+
'Attribute ":ab" should go before ":abc".'
2280+
]
2281+
},
2282+
{
2283+
filename: 'test.vue',
2284+
code: `
2285+
<template>
2286+
<div
2287+
very-long-binding="longerValue"
2288+
short="obj"
2289+
@click="fn">
2290+
</div>
2291+
</template>`,
2292+
output: `
2293+
<template>
2294+
<div
2295+
short="obj"
2296+
very-long-binding="longerValue"
2297+
@click="fn">
2298+
</div>
2299+
</template>`,
2300+
options: [{ sortLineLength: true }],
2301+
errors: ['Attribute "short" should go before "very-long-binding".']
2302+
},
2303+
{
2304+
filename: 'test.vue',
2305+
code: `
2306+
<template>
2307+
<div
2308+
aa="v"
2309+
z="v"
2310+
></div>
2311+
</template>`,
2312+
output: `
2313+
<template>
2314+
<div
2315+
z="v"
2316+
aa="v"
2317+
></div>
2318+
</template>`,
2319+
options: [{ sortLineLength: true, alphabetical: true }],
2320+
errors: [{ message: 'Attribute "z" should go before "aa".' }]
2321+
},
2322+
{
2323+
filename: 'test.vue',
2324+
code: `
2325+
<template>
2326+
<div
2327+
zz="v"
2328+
bb="v"
2329+
@keyup="fn"
2330+
@click="fn"
2331+
></div>
2332+
</template>`,
2333+
output: `
2334+
<template>
2335+
<div
2336+
bb="v"
2337+
zz="v"
2338+
@click="fn"
2339+
@keyup="fn"
2340+
></div>
2341+
</template>`,
2342+
options: [{ sortLineLength: true, alphabetical: true }],
2343+
errors: [
2344+
{ message: 'Attribute "bb" should go before "zz".' },
2345+
{ message: 'Attribute "@click" should go before "@keyup".' }
2346+
]
21052347
}
21062348
]
21072349
})

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /