@@ -22,20 +22,44 @@ const kebabCaseElements = [
2222 'missing-glyph'
2323]
2424
25+ // https://vuejs.org/v2/api/index.html#Built-In-Components
26+ const vueBuiltInComponents = [
27+ 'component' ,
28+ 'transition' ,
29+ 'transition-group' ,
30+ 'keep-alive' ,
31+ 'slot'
32+ ]
33+
34+ const vue3BuiltInComponents = [
35+ 'teleport' ,
36+ 'suspense'
37+ ]
38+
2539const isLowercase = ( word ) => / ^ [ a - z ] * $ / . test ( word )
2640const capitalizeFirstLetter = ( word ) => word [ 0 ] . toUpperCase ( ) + word . substring ( 1 , word . length )
2741
28- const RESERVED_NAMES = new Set (
29- [
30- ...kebabCaseElements ,
31- ...kebabCaseElements . map ( casing . pascalCase ) ,
32- ...htmlElements ,
33- ...htmlElements . map ( capitalizeFirstLetter ) ,
34- ...deprecatedHtmlElements ,
35- ...deprecatedHtmlElements . map ( capitalizeFirstLetter ) ,
36- ...svgElements ,
37- ...svgElements . filter ( isLowercase ) . map ( capitalizeFirstLetter )
38- ] )
42+ const RESERVED_NAMES_IN_HTML = new Set ( [
43+ ...htmlElements ,
44+ ...htmlElements . map ( capitalizeFirstLetter )
45+ ] )
46+ const RESERVED_NAMES_IN_VUE = new Set ( [
47+ ...vueBuiltInComponents ,
48+ ...vueBuiltInComponents . map ( casing . pascalCase )
49+ ] )
50+ const RESERVED_NAMES_IN_VUE3 = new Set ( [
51+ ...RESERVED_NAMES_IN_VUE ,
52+ ...vue3BuiltInComponents ,
53+ ...vue3BuiltInComponents . map ( casing . pascalCase )
54+ ] )
55+ const RESERVED_NAMES_IN_OTHERS = new Set ( [
56+ ...deprecatedHtmlElements ,
57+ ...deprecatedHtmlElements . map ( capitalizeFirstLetter ) ,
58+ ...kebabCaseElements ,
59+ ...kebabCaseElements . map ( casing . pascalCase ) ,
60+ ...svgElements ,
61+ ...svgElements . filter ( isLowercase ) . map ( capitalizeFirstLetter )
62+ ] )
3963
4064// ------------------------------------------------------------------------------
4165// Rule Definition
@@ -46,14 +70,41 @@ module.exports = {
4670 type : 'suggestion' ,
4771 docs : {
4872 description : 'disallow the use of reserved names in component definitions' ,
49- categories : undefined , // 'essential'
73+ categories : undefined ,
5074 url : 'https://eslint.vuejs.org/rules/no-reserved-component-names.html'
5175 } ,
5276 fixable : null ,
53- schema : [ ]
77+ schema : [ {
78+ type : 'object' ,
79+ properties : {
80+ disallowVueBuiltInComponents : {
81+ type : 'boolean'
82+ } ,
83+ disallowVue3BuiltInComponents : {
84+ type : 'boolean'
85+ }
86+ }
87+ } ] ,
88+ messages : {
89+ reserved : 'Name "{{name}}" is reserved.' ,
90+ reservedInHtml : 'Name "{{name}}" is reserved in HTML.' ,
91+ reservedInVue : 'Name "{{name}}" is reserved in Vue.js.' ,
92+ reservedInVue3 : 'Name "{{name}}" is reserved in Vue.js 3.x.'
93+ }
5494 } ,
5595
5696 create ( context ) {
97+ const options = context . options [ 0 ] || { }
98+ const disallowVueBuiltInComponents = options . disallowVueBuiltInComponents === true
99+ const disallowVue3BuiltInComponents = options . disallowVue3BuiltInComponents === true
100+
101+ const reservedNames = new Set ( [
102+ ...RESERVED_NAMES_IN_HTML ,
103+ ...( disallowVueBuiltInComponents ? RESERVED_NAMES_IN_VUE : [ ] ) ,
104+ ...( disallowVue3BuiltInComponents ? RESERVED_NAMES_IN_VUE3 : [ ] ) ,
105+ ...RESERVED_NAMES_IN_OTHERS
106+ ] )
107+
57108 function canVerify ( node ) {
58109 return node . type === 'Literal' || (
59110 node . type === 'TemplateLiteral' &&
@@ -70,15 +121,17 @@ module.exports = {
70121 } else {
71122 name = node . value
72123 }
73- if ( RESERVED_NAMES . has ( name ) ) {
124+ if ( reservedNames . has ( name ) ) {
74125 report ( node , name )
75126 }
76127 }
77128
78129 function report ( node , name ) {
79130 context . report ( {
80131 node : node ,
81- message : 'Name "{{name}}" is reserved.' ,
132+ messageId : RESERVED_NAMES_IN_HTML . has ( name ) ? 'reservedInHtml'
133+ : RESERVED_NAMES_IN_VUE . has ( name ) ? 'reservedInVue'
134+ : RESERVED_NAMES_IN_VUE3 . has ( name ) ? 'reservedInVue3' : 'reserved' ,
82135 data : {
83136 name : name
84137 }
@@ -98,7 +151,7 @@ module.exports = {
98151 utils . executeOnVue ( context , ( obj ) => {
99152 // Report if a component has been registered locally with a reserved name.
100153 utils . getRegisteredComponents ( obj )
101- . filter ( ( { name } ) => RESERVED_NAMES . has ( name ) )
154+ . filter ( ( { name } ) => reservedNames . has ( name ) )
102155 . forEach ( ( { node, name } ) => report ( node , name ) )
103156
104157 const node = obj . properties
0 commit comments