vuejs / eslint-plugin-vue

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

Rule proposal: `slot-name-casing` #2580

Open markbrockhoff opened 1 month ago

markbrockhoff commented 1 month ago

Please describe what the rule should do: The proposed linter rule should allow limiting the casing for slot names. For example in bigger projects it might happen that people mix camelCase and kebab-case for the names of component slots. To keep the codebase uniform it would be really helpful if a linter rule would warn or optionally even automatically fix invalid slot names according to the projects configuration.

What category should the rule belong to?

[x] Enforces code style (layout) [ ] Warns about a potential error (problem) [ ] Suggests an alternate way of doing something (suggestion) [ ] Other (please specify:)

Provide 2-3 code examples that this rule should warn about:

Bad:

<template>
  <div>
    <slot name="random-Slot_name" />
  </div>
</template

Good:

<template>
  <div>
    <slot name="randomSlotName" />
  </div>
</template

Good:

<template>
  <div>
    <slot name="random-slot-name" />
  </div>
</template

Additional context It would most likely be enough to detect invalid slot names when a slot is defined. While fixing invalid usage of slots would be nice for existing projects adapting the rule but might also blow up it's complexity.

FloEdelmann commented 1 month ago

Makes sense. It should have a single option that defines the style to use (kebab-case or camelCase), similar to vue/prop-name-casing. Which style should be the default? Which one is used more often in the official Vue documentation?

PR welcome to implement the rule!

markbrockhoff commented 1 month ago

The vue docs ship around this discussion by only using single word slot names. But personally I'd prefer camelCase as default for slot names. This would also be in line with the default of prop-name-casing. However I don't have a strong opinion about it, as long as its consistend across a project.

So if anyone else has good arguments for or against using camelCase as default please feel free to put them here :)

FloEdelmann commented 1 month ago

Thanks for checking! camelCase seems like a sensible default, because it allows using e.g. this.$slots.mySlot() instead of an awkward this.$slots['my-slot']().

jacekkarczmarczyk commented 1 month ago

On the other hand camelCase might not work properly in in-dom templates

FloEdelmann commented 1 month ago

That's true and it should be mentioned in the rule's documentation. Thanks for bringing that up!

However, I think that it shouldn't dictate the rule's default style because…

  1. … in-DOM templates are probably a minority use-case, at least among eslint-plugin-vue users.
  2. … other rules such as vue/html-self-closing also have a default that is incompatible with in-DOM templates, see https://vuejs.org/guide/essentials/component-basics.html#self-closing-tags.
  3. … this rule is not part of a shared config (yet), so users have to explicitly enable it.
jacekkarczmarczyk commented 1 month ago

How about having 3 options: camelCase, kebab-case and singleword? Single word might be prefered by some as it doesn't have issues that the 2 other options have and I think it doesn't make sense to create a seperate rule for that.

FloEdelmann commented 1 month ago

That's a good idea! Then singleword could be the default, aligned with the Vue documentation and also compatible with in-DOM templates.

markbrockhoff commented 1 month ago

I like the idea of having a singleword option but feel like it could be a bit limiting as a default. I think a lot of projects would need to change this default to one of the other casings which imho kinda defeats the purpose of a "default". Especially as single words are both valid camelCase and kebab-case I think using it as (reasonable) default is too strict.

I personally would rather vote for using "camelCase" as default and documenting the option for projects deciding to be more strict or wanting to use in-dom templates.