vuejs / eslint-plugin-vue

Official ESLint plugin for Vue.js
https://eslint.vuejs.org/
MIT License
4.47k stars 667 forks source link

`vue/attribute-hyphenation` autofix breaks the `.sync` modifier #2521

Closed kricsleo closed 2 months ago

kricsleo commented 3 months ago

Checklist

Tell us about your environment

Please show your full configuration:

I'am using antfu's @antfu/eslint-config

Remember I've set the vue/v-on-event-hyphenation rule's config autofix tobe false.

import eslint from '@antfu/eslint-config';

export default eslint({
  rules: {
    'vue/attribute-hyphenation': ['error', 'never'],
    'vue/v-on-event-hyphenation': ['error', 'never', {
      autofix: false
    }],
  },

  vue: {
    vueVersion: 2,
  },
});

What did you do?

Suppose this:

<Hi :my-name.sync="name" />

Then running eslint . --fix

After the autofix of vue/attribute-hyphenation, code becomes:

<Hi :myName.sync="name" />

This code should not be autofixed, because .sync means this is actually a shorthand of:

<Hi :my-name="name" @update:my-name="name = $event" />

When it's autofixed to the this code:

<Hi :myName.sync="name" />

It means:

<Hi :myName="name" @update:myName="name = $event" />

And this autofixed code would break, because the event name should be update:my-name, instead of update:myName.

Might be solution

https://github.com/vuejs/eslint-plugin-vue/blob/66e3201e17eee2bb45d2e0e98018e7de5481cb0c/lib/rules/attribute-hyphenation.js#L99-L108

Maybe we can add another .sync check here(willing to contribute a PR for this), for example:

fix: (fixer) => {
  if (text.includes('_')) {
    return null
  }

  if (/^[A-Z]/.test(name)) {
    return null
  }

+ if(text.endsWith('.sync')) {
+   return null
+ }

  return fixer.replaceText(
    node.key,
    text.replace(name, caseConverter(name))
  )
}