-
-
Notifications
You must be signed in to change notification settings - Fork 681
/
Copy pathno-unused-components.js
100 lines (92 loc) · 3.37 KB
/
no-unused-components.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
/**
* @fileoverview Report used components
* @author Michał Sajnóg
*/
'use strict'
// ------------------------------------------------------------------------------
// Requirements
// ------------------------------------------------------------------------------
const utils = require('../utils')
const casing = require('../utils/casing')
// ------------------------------------------------------------------------------
// Rule Definition
// ------------------------------------------------------------------------------
module.exports = {
meta: {
docs: {
description: 'disallow registering components that are not used inside templates',
category: 'essential',
url: 'https://github.com/vuejs/eslint-plugin-vue/blob/v5.0.0-beta.3/docs/rules/no-unused-components.md'
},
fixable: null,
schema: [{
type: 'object',
properties: {
ignoreWhenBindingPresent: {
type: 'boolean'
}
},
additionalProperties: false
}]
},
create (context) {
const options = context.options[0] || {}
const ignoreWhenBindingPresent = options.ignoreWhenBindingPresent !== undefined ? options.ignoreWhenBindingPresent : true
const usedComponents = []
let registeredComponents = []
let ignoreReporting = false
let templateLocation
return utils.defineTemplateBodyVisitor(context, {
VElement (node) {
if (utils.isHtmlElementNode(node) && !utils.isHtmlWellKnownElementName(node.rawName)) {
usedComponents.push(node.rawName)
}
},
"VAttribute[directive=true][key.name='bind'][key.argument='is']" (node) {
if (node.value.type !== 'VExpressionContainer') return
if (node.value.expression.type === 'Literal') {
usedComponents.push(node.value.expression.value)
} else if (ignoreWhenBindingPresent) {
ignoreReporting = true
}
},
"VAttribute[directive=false][key.name='is']" (node) {
usedComponents.push(node.value.value)
},
"VElement[name='template']" (rootNode) {
templateLocation = templateLocation || rootNode.loc.start
},
"VElement[name='template']:exit" (rootNode) {
if (
rootNode.loc.start !== templateLocation ||
ignoreReporting
) return
registeredComponents
.filter(({ name }) => {
// If the component name is PascalCase or camelCase
// it can be used in various of ways inside template,
// like "theComponent", "The-component" etc.
// but except snake_case
if (casing.pascalCase(name) === name || casing.camelCase(name) === name) {
return !usedComponents.some(n => {
return n.indexOf('_') === -1 && (name === casing.pascalCase(n) || casing.camelCase(n) === name)
})
} else {
// In any other case the used component name must exactly match
// the registered name
return usedComponents.indexOf(name) === -1
}
})
.forEach(({ node, name }) => context.report({
node,
message: 'The "{{name}}" component has been registered but not used.',
data: {
name
}
}))
}
}, utils.executeOnVue(context, (obj) => {
registeredComponents = utils.getRegisteredComponents(obj)
}))
}
}