Eslint-plugin-vue: vue/component-name-in-template-casing does not work simultaneously with kebab-case and PascalCase.

Created on 6 Dec 2018  路  5Comments  路  Source: vuejs/eslint-plugin-vue

Tell us about your environment

  • ESLint version: 5.9.0
  • eslint-plugin-vue version: 3.2.1
  • Node version: 10.14.1

Please show your full configuration:

{
  "name": "test",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint"
  },
  "dependencies": {
    "vue": "^2.5.17"
  },
  "devDependencies": {
    "@vue/cli-plugin-babel": "^3.2.0",
    "@vue/cli-plugin-eslint": "^3.2.0",
    "@vue/cli-service": "^3.2.0",
    "babel-eslint": "^10.0.1",
    "eslint": "^5.8.0",
    "eslint-plugin-vue": "^5.0.0-0",
    "vue-template-compiler": "^2.5.17"
  },
  "eslintConfig": {
    "root": true,
    "env": {
      "node": true
    },
    "extends": [
      "plugin:vue/recommended",
      "eslint:recommended"
    ],
    "parserOptions": {
      "parser": "babel-eslint"
    }
  },
  "postcss": {
    "plugins": {
      "autoprefixer": {}
    }
  },
  "browserslist": [
    "> 1%",
    "last 2 versions",
    "not ie <= 8"
  ]
}

What did you do?

  1. Create a new project in vue ui with default template;
  2. In vue ui open Configuration -> ESLint configuration -> Rules tab + select Error for vue/component-name-in-template-casing + Save settings;
  3. Open App.vue and add, for example <hello-world msg="Welcome to Your Vue.js App"/> next to <HelloWorld msg="Welcome to Your Vue.js App"/>. Save changes;
  4. In package.json, to the section rules, try to add either:

a) According to this info:

  "vue/component-name-in-template-casing": ["error",
    "PascalCase|kebab-case",
    {
      "ignores": []
    }
  ] 

or b) According to this info:

  "vue/component-name-in-template-casing": ["error", 
     "PascalCase" | "kebab-case", 
     { 
        "ignores": []
      }
    ]

What did you expect to happen?
vue/component-name-in-template-casing should work with kebab-case and PascalCase simultaneously.

What actually happened?
kebab-case and PascalCase does not work simultaneously.

All 5 comments

Thank you for this issue.
This option can only be one of PascalCase or kebab-case.

Could this issue be a feature request?

PascalCase can be preferable, when developer wants to highlight, for example:

  • its own components;
  • external component which solves one issue.

and kebab-case could be preferable, when component should not stand out from other code, for example:

  • when external component is used everywhere / many times, for example bootsrap-vue.

Thank you.

It's kind of hard to picture 馃
Could you give me examples of specific source code?

Easy :)

    <div :style="{'max-height': maxHeightBlock + 'px', 'overflow-y': 'auto'}">
      <component :is="stateSourcesWithoutSubHeaders.includes(stateSource) ? 'div' : 'b-card' "
                 v-for="playlistOrTagObj in getStateSource[fields.subHeaderItemsType]"
                 :key="playlistOrTagObj[fields.subHeaderItemTitle]"
                 no-body bg-variant="light" text-variant="black" class="mb-1">

        <div v-if="!stateSourcesWithoutSubHeaders.includes(stateSource)" class="d-flex w-100 align-items-center">
          <div class="mr-auto pl-2">
            <b-form-checkbox :indeterminate="playlistOrTagObj[fields.isSubHeaderIndeterminate]"
                             v-model="playlistOrTagObj[fields.isSubHeaderSelected]"
                             @change="subHeaderSelection({tabName: tabName,
                                                          stateSource: stateSource,
                                                          nameOrId: playlistOrTagObj[fields.subHeaderItemTitle]})">

              <b>{{ playlistOrTagObj[fields.subHeaderItemTitle] }}</b>
            </b-form-checkbox>
          </div>

          <b-badge class="mr-3" variant="primary" pill>{{ playlistOrTagObj.tracks.length }}</b-badge>

          <div @click="playlistOrTagObj[fields.isSubHeaderMaximized]=!playlistOrTagObj[fields.isSubHeaderMaximized]"
               class="p-2">
            <template v-if="playlistOrTagObj[fields.isSubHeaderMaximized]">
              <b-img :src="require('./assets/collapse.svg')"></b-img>
            </template>
            <template v-else>
              <b-img :src="require('./assets/expand.svg')"></b-img>
            </template>
          </div>
        </div>

        <VueDraggable v-model="playlistOrTagObj.tracks"
                       v-show="playlistOrTagObj[fields.isSubHeaderMaximized]"
                      class="swiper-no-swiping">
          <div v-for="(trackObj, index) in playlistOrTagObj.tracks" :key="trackObj.youtubeTrackId">
            <div class="d-flex" :style="{'cursor': 'row-resize', 'user-select': 'none'}">
              <b-form-checkbox v-model="trackObj[fields.isTrackSelected]"
                               @change="trackSelection({tabName: tabName,
                                                      stateSource: stateSource,
                                                      tagOrPlaylistOrSearchObj: playlistOrTagObj})"
                               :class="stateSourcesWithoutSubHeaders.includes(stateSource) ? 'mr-0' : 'ml-4 mr-0'">
              </b-form-checkbox>

              <div v-show="showThumbnail">
                <b-img :src="trackObj.youtubeTrackThumbnails === undefined ? '' : trackObj.youtubeTrackThumbnails.default.url"
                       :alt="'Thumbnail of ' + trackObj.youtubeTrackTitle" thumbnail fluid/>
              </div>

              <b-card @click="nextTrack({whatToDo: 'playTrackObj', youtubeTrackObj: trackObj})" no-body
                      class="w-100 pl-2">
                {{ index + 1 }}. {{ trackObj.youtubeTrackTitle }}
              </b-card>
            </div>
          </div>
        </VueDraggable>
      </component>
    </div>

As you can see, I have lots of b-* components from bootstrap-vue and I use them in lowercase / kebab-case as the rest html (such as <div>, <b>) or vue (such as <template>, <component>) tags, because b-* tags under the hood actually are a simple html markup tags. So this is the reason I use kebab-case, because I want them to look like traditional lowercase html tags.

In contrast you can find in the code above VueDraggable, whose role is out of scope of html markup, so in order to highlight it against the html markup I prefer to use PascalCase.

@TitanFighter Thanks for the additional information.

I think that it is a new rule to force PascalCase or kebab-case for the feature of each component.

However, the style guide recommends that component names should always be PascalCase.
(Users of bootstrap-vue can not use PascalCase because the component definition ofbootstrap-vue does not follow the style guide.)
https://vuejs.org/v2/style-guide/index.html#Component-name-casing-in-templates-strongly-recommended

I think we need to consider ways in which these do not conflict.

You can open a new issue using the "Rule Proposal" template and discuss it.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Hyzual picture Hyzual  路  3Comments

rodneyrehm picture rodneyrehm  路  4Comments

filipalacerda picture filipalacerda  路  4Comments

prograhammer picture prograhammer  路  3Comments

KristofMorva picture KristofMorva  路  4Comments