eslint-plugin-vue
                                
                                 eslint-plugin-vue copied to clipboard
                                
                                    eslint-plugin-vue copied to clipboard
                            
                            
                            
                        component-name-in-template-casing breaks components with native element clashes
If a component is registered with the name of a native element, this rule converts instances of the native element into the component. (ie <button> gets converted to <Button>)
I know it's not ideal to have components named after base HTML elements, but linters also shouldn't break code either.
I'd say the conversion shouldn't happen if the offending element is lowercase and a native html element.
Tell us about your environment
- ESLint version: 6.8.0
- eslint-plugin-vue version: 6.2.2
- Node version: 10.16.3
Please show your full configuration:
module.exports = {
  env: {
    browser: true,
    node: true,
    es6: true,
  },
  extends: ['eslint:recommended', 'prettier'],
  ignorePatterns: ['node_modules', ''],
  parser: 'babel-eslint',
  parserOptions: {
    sourceType: 'module',
  },
  plugins: ['import'],
  rules: {
    // Only allow debugger in development
    'no-debugger': process.env.PRE_COMMIT ? 'error' : 'off',
    // Only allow `console.log` in development
    'no-console': process.env.PRE_COMMIT
      ? ['error', { allow: ['warn', 'error'] }]
      : 'off',
    'import/no-relative-parent-imports': 'warn',
    'import/order': 'error',
    'no-unused-vars': 'warn',
  },
  overrides: [
    // Vue things
    {
      files: ['*.vue', 'vue-utils/*.js'],
      parser: 'vue-eslint-parser',
      parserOptions: {
        parser: 'babel-eslint',
        sourceType: 'module',
      },
      extends: [
        // vue-eslint rule documentation
        // https://eslint.vuejs.org/rules/#priority-c-recommended-minimizing-arbitrary-choices-and-cognitive-overhead
        // the config files in the repo are also useful to check:
        // https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/configs/recommended.js
        'plugin:vue/recommended',
        'prettier/vue',
      ],
      rules: {
        'vue/name-property-casing': ['warn', 'kebab-case'],
        // this seems like a good idea: current offenders: Link, Button, Picture, Select
        'vue/no-reserved-component-names': 'warn',
        // disabling this rule as some of our prop definitions with the spread operator STILL cause it to break sometimes.
        'vue/require-default-prop': 'off',
        // disabling this for now since it conflicts with our template formatting through vetur/prettyhtml.
        'vue/multiline-html-element-content-newline': 'off',
        // we want camelcase, but it interferes our mixin namespacing style
        'vue/camelcase': 'off',
        // misc extra and js formatting rules for vue https://eslint.vuejs.org/rules/
        'vue/array-bracket-spacing': 'error',
        'vue/arrow-spacing': 'error',
        'vue/block-spacing': 'error',
        'vue/brace-style': 'error',
        'vue/comma-dangle': ['error', 'always-multiline'],
        'vue/component-name-in-template-casing': 'error',
        'vue/dot-location': ['error', 'property'],
        'vue/eqeqeq': 'error',
        'vue/key-spacing': 'error',
        'vue/keyword-spacing': 'error',
        'vue/no-boolean-default': ['error', 'default-false'],
        'vue/no-deprecated-scope-attribute': 'error',
        'vue/no-empty-pattern': 'error',
        'vue/object-curly-spacing': ['error', 'always'],
        'vue/space-infix-ops': 'error',
        'vue/space-unary-ops': 'error',
        'vue/v-on-function-call': 'error',
        'vue/v-slot-style': [
          'error',
          {
            atComponent: 'v-slot',
            default: 'shorthand',
            named: 'shorthand',
          },
        ],
        'vue/valid-v-slot': 'error',
      },
    },
    // test files
    {
      files: ['**/*.test.js', '**/*.test.example.js'],
      rules: {
        'no-unused-vars': 'off',
      },
      env: { jest: true, browser: false },
    },
    // Stories
    {
      files: ['*.stories.js'],
      rules: {
        'no-unused-vars': 'off',
        'import/no-relative-parent-imports': 'off',
      },
    },
    // Dev Scripts
    {
      files: ['./dev/**/*.js'],
      rules: {
        'no-console': 'off',
      },
    },
  ],
};
What did you do?
<template>
  <div>
    <button>hello</button>
    <Button label="hello"/>
  </div>
</template>
<script>
import Button from './Button';
export default {
  components: {Button}
}
</script>
What did you expect to happen? nothing
What actually happened?
<template>
  <div>
    <Button>hello</Button>
    <Button label="hello"/>
  </div>
</template>
Well, actually, as you may know, Vue.js has a style guide, and it is considered an essential practice that you always name your components with two words or more.
The reasoning behind this recommendation is really to avoid this kind of problem you are having, as Vue supports templating within the html, it recommends multi-word naming to not conflict with default html's ones.
The essential rules have a warning at the top of the document as following:
These rules help prevent errors, so learn and abide by them at all costs
I mean, to avoid your issue, we (I'm not a maintainer, nor never touched this repo's code, I'm here just trying to help :sweat_smile:) would have to ignore all lowercase single-worded components, but can we call this rule fixable them? if it doesn't fix all cases?
I'd say the value of having the --fix option is bigger than the issue you are having, because, the way I see it, you, with this particular case, can always insert all the non-recommended names you are using in your project in the ignore array:
'vue/component-name-in-template-casing': ['error', 'PascalCase', {
  ignores: ['button', /* any other instance of this issue */],
}],
I'd recommend this approach, at very least as a workaround for now, I do understand your point, but I think the cost of having to maintain a list of all html elements not ideal at all.
(Them again, I'm not a contributor, so if anything I said, bothered you in any manner, please, don't associate my comment to the lib itself, have a great day :smile:)
Reference: https://vuejs.org/v2/style-guide/#Multi-word-component-names-essential
Thanks for the feedback, you may have noted that in the issue I acknowledged it is a bad practice and I already understand why it should be avoided (fwiw: my team started using Vue before the styleguide existed and never used dom templates and instead used the variable name, which has caused literally 0 issues.. even this one is because of a component named after a native HTML element which isn't quite the same thing.. but I digress)
Absolutely the --fix is valuable, but in my issue I already suggested a way of reliably working around it (checking against native html elements and leaving those ones alone). Although an even simpler way of programatically avoiding this problem: not fixing single word components in general since they're not following the styleguide and it could cause problems.. you mentioned that as not 'fixable' anymore.. i think it still would be
Is this still an issue?
Also note that there is the vue/no-reserved-component-names rule that disallows component names used as HTML element names.