-
-
Notifications
You must be signed in to change notification settings - Fork 681
[New] Add vue/attribute-order
#209
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
Conversation
9a5c7b8
to
7dc3e5b
Compare
Hey @erindepew Are you willing to work on this further on? If yes - let us know and please see last comments in #209 for more informations about possible solutions :) |
@michalsnik sure! I was just waiting for the community to decide if they want a configuration option and if so what it should be. Are you referring to #170 (comment) ? |
Cool! Sort of, but you know what? Let's start with a simple implementation that does job well according to the official style guide, that is: let's pre-define groups of attributes and only allow people to change order of those groups in configuration, but not individual attributes. So the default configuration could look just like this:
Groups should obviously reflect situation from style guide. After it's done we can iterate and add custom groups support / think about possible edge scenarios etc. WDYT? |
@michalsnik I'm going to assume that it makes sense to push off ordering them alphabetically within those groups for a future iteration? |
4a71322
to
c4112b5
Compare
@michalsnik updated, let me know what you think! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you @erindepew for your work :) I added some comments.
@chrisvfritz could you please also take a look from a broader perspective?
docs/rules/attribute-order.md
Outdated
:+1: Examples of **correct** code with custom order`: | ||
|
||
```html | ||
<!-- options: [{ order: ['LIST_RENDERING', 'CONDITIONALS', 'RENDER_MODIFIERS', 'GLOBAL', 'UNIQUE', 'BINDING', 'OTHER_ATTR', 'EVENTS', 'CONTENT', 'DEFINITION'] }] --> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should use eslint-ready format here, so it's not confusing for users:
<!-- 'vue/attribute-order': [2, { order: [...] }] -->
docs/rules/attribute-order.md
Outdated
@@ -0,0 +1,93 @@ | |||
# enforce ordering of attributes (attribute-order) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd go with attributes-order
docs/rules/attribute-order.md
Outdated
|
||
## :book: Rule Details | ||
|
||
This rule aims to enfore ordering of component attributes. The default order is specified in the [Vue styleguide](https://vuejs.org/v2/style-guide/#Element-attribute-order-recommended). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you could add default order here as a simple list:
- LIST_RENDERING
- CONDITIONALS
...and so on
and then link to official styleguide for more informations. But users should be able to quickly pick up what's going on by just looking at rule documentation :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that we could even give examples for each category, what attributes does it expect actually. I think it would be a huge help!
lib/rules/attribute-order.js
Outdated
function getPosition (attribute, attributeOrder) { | ||
const name = attribute.key.name | ||
if (name === 'is') { | ||
return attributeOrder.indexOf('DEFINITION') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you could add function getAttributeType
that would return DEFINITION
, LIST_RENDERING
and so on.
Then you could shorthen this function to:
const attributeType = getAttributeType(attribute.key.name)
return attributeOrder.indexOf(attributeType)
This way you'd eliminate multiple attributeOrder.indexOf
duplication and make it even more readable :) WDYT?
lib/rules/attribute-order.js
Outdated
module.exports = { | ||
meta: { | ||
docs: { | ||
description: 'enforce ordering of attributes', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think about: enforce order of attributes
?
lib/rules/attribute-order.js
Outdated
|
||
return utils.defineTemplateBodyVisitor(context, { | ||
'VStartTag' () { | ||
currentPosition = -1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Theoretically you should also reset previousNode here, though it won't throw error now, because of the fact that previousNode is used after it's redefined in previous conditions of VAttribute
tests/lib/rules/attribute-order.js
Outdated
}) | ||
tester.run('attribute-order', rule, { | ||
|
||
valid: [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add some cases with shorthanded bindings
lib/rules/attribute-order.js
Outdated
context.report({ | ||
node: node.key, | ||
loc: node.loc, | ||
message: `Attribute ${currentNode} must go before ${prevNode}.`, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add "
around attributes. Also I'm thinking whether the message shouldn't be more gentle and say should
instead of must
lib/rules/attribute-order.js
Outdated
} else if (name === 'model') { | ||
return attributeOrder.indexOf('BINDING') | ||
} else if (name === 'on') { | ||
return attributeOrder.indexOf('EVENTS') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it catch both v-on
and @
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yup! I'm using @click
in my tests and it seems to work fine, I'll also add v-on
just to be sure
lib/rules/attribute-order.js
Outdated
} else if (name === 'ref' || name === 'key' || name === 'slot') { | ||
return attributeOrder.indexOf('UNIQUE') | ||
} else if (name === 'model') { | ||
return attributeOrder.indexOf('BINDING') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
v-bind:something
and :something
should also be marked as binding I think, not only v-model
.
Also what if someone adds property model="asd"
? I think it would mark it as binding and not OTHER_ATTR. You should probably check if attribute.directive
is true in all cases where you want to detect v-
attribute.
README.md
Outdated
@@ -161,7 +161,7 @@ Enforce all the rules in this category, as well as all higher priority rules, wi | |||
| | [require-prop-types](./docs/rules/require-prop-types.md) | require type definitions in props | | |||
| :wrench: | [v-bind-style](./docs/rules/v-bind-style.md) | enforce `v-bind` directive style | | |||
| :wrench: | [v-on-style](./docs/rules/v-on-style.md) | enforce `v-on` directive style | | |||
|
|||
| :wrench: | [attribute-order](./docs/rules/attribute-order.md) | enforce ordering of attributes | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you add it by hand? I see there is fixable
set to null in rule, but I also see 🔧 here. Please run npm run update
if you want to update readme or rule documentation header base on rule source.
c4112b5
to
dfb2b58
Compare
dfb2b58
to
5bc45a4
Compare
@michalsnik yup, that all makes sense. Updated! |
Hey @erindepew, I'll take a closer look and test run soon :) So far it's looking very promising 🚀 A little advice for the future though: please try not to rebase during review, as people that check your code after review once again can't see actual changes you performed in order to resolve given suggestions. Rebasing is good right before requesting review or after review :) |
docs/rules/attributes-order.md
Outdated
- UNIQUE | ||
ex: 'ref', 'key', 'slot' | ||
- BINDING | ||
ex: 'v-model', 'v-bind' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does :something=""
count here too?
docs/rules/attributes-order.md
Outdated
- OTHER_ATTR | ||
ex: 'customProp="foo"' | ||
- EVENTS | ||
ex: '@click="functionCall"' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does v-on=""
count here too?
docs/rules/attributes-order.md
Outdated
is="header" | ||
v-for="item in items" | ||
v-if="!visible" | ||
v-once id="uniqueID" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why there are two attributes in the same line here?
tests/lib/rules/attributes-order.js
Outdated
}, | ||
{ | ||
filename: 'test.vue', | ||
code: '<template><div is="header" v-for="item in items" v-if="!visible" v-once id="uniqueID" ref="header" v-model="headerData" myProp="prop" @click="functionCall" v-text="textContent"></div></template>' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should wrap those lines so it's easier to read :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for this Erin! I just saw one more thing to update from my perspective. 🙂
lib/rules/attributes-order.js
Outdated
docs: { | ||
description: 'enforce order of attributes', | ||
category: undefined, | ||
recommended: false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can go in the recommended
category and we can remove recommended: false
, since we no longer use that property.
Thanks @chrisvfritz and @michalsnik for the review! I made the suggested changes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎉
This looks great! Would love to get this merged so our team can start taking advantage of it. Anything still outstanding here? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's give it a spin! :D
Congrats @erindepew! |
Hey! Thanks for this awesome rule @erindepew ! There was a discussion and some comments about making alphabetical order within groups, is this implemented? The documentation does not state anything related 🤔 |
resolves #170