diff --git a/lib/rules/name-property-casing.js b/lib/rules/name-property-casing.js
index d86435a95..29c100db5 100644
--- a/lib/rules/name-property-casing.js
+++ b/lib/rules/name-property-casing.js
@@ -19,10 +19,10 @@ module.exports = {
description:
'enforce specific casing for the name property in Vue components',
categories: ['vue3-strongly-recommended', 'strongly-recommended'],
- url: 'https://eslint.vuejs.org/rules/name-property-casing.html',
- replacedBy: ['component-definition-name-casing']
+ url: 'https://eslint.vuejs.org/rules/name-property-casing.html'
},
deprecated: true,
+ replacedBy: ['component-definition-name-casing'],
fixable: 'code', // or "code" or "whitespace"
schema: [
{
diff --git a/lib/rules/no-confusing-v-for-v-if.js b/lib/rules/no-confusing-v-for-v-if.js
index 4135f163a..1842f7c8c 100644
--- a/lib/rules/no-confusing-v-for-v-if.js
+++ b/lib/rules/no-confusing-v-for-v-if.js
@@ -43,10 +43,10 @@ module.exports = {
docs: {
description: 'disallow confusing `v-for` and `v-if` on the same element',
categories: ['vue3-recommended', 'recommended'],
- url: 'https://eslint.vuejs.org/rules/no-confusing-v-for-v-if.html',
- replacedBy: ['no-use-v-if-with-v-for']
+ url: 'https://eslint.vuejs.org/rules/no-confusing-v-for-v-if.html'
},
deprecated: true,
+ replacedBy: ['no-use-v-if-with-v-for'],
fixable: null,
schema: []
},
diff --git a/lib/rules/no-undef-components.js b/lib/rules/no-undef-components.js
index aa9ddb0dd..e56f0412c 100644
--- a/lib/rules/no-undef-components.js
+++ b/lib/rules/no-undef-components.js
@@ -202,9 +202,10 @@ module.exports = {
const nameProperty = utils.findProperty(obj, 'name')
- if (nameProperty) {
- if (nameProperty.value.type === 'Literal') {
- registeredComponentNames.push(`${nameProperty.value.value}`)
+ if (nameProperty && utils.isStringLiteral(nameProperty.value)) {
+ const name = utils.getStringLiteralValue(nameProperty.value)
+ if (name) {
+ registeredComponentNames.push(name)
}
}
diff --git a/lib/rules/no-unregistered-components.js b/lib/rules/no-unregistered-components.js
index efd265e55..4ba755dd3 100644
--- a/lib/rules/no-unregistered-components.js
+++ b/lib/rules/no-unregistered-components.js
@@ -44,10 +44,10 @@ module.exports = {
'disallow using components that are not registered inside templates',
categories: null,
recommended: false,
- url: 'https://eslint.vuejs.org/rules/no-unregistered-components.html',
- replacedBy: ['no-undef-components']
+ url: 'https://eslint.vuejs.org/rules/no-unregistered-components.html'
},
deprecated: true,
+ replacedBy: ['no-undef-components'],
fixable: null,
schema: [
{
diff --git a/lib/rules/no-unused-properties.js b/lib/rules/no-unused-properties.js
index 74762e446..1414df359 100644
--- a/lib/rules/no-unused-properties.js
+++ b/lib/rules/no-unused-properties.js
@@ -586,8 +586,7 @@ module.exports = {
}
}),
{
- /** @param {Program} node */
- 'Program:exit'(node) {
+ Program() {
const styleVars = getStyleVariablesContext(context)
if (styleVars) {
templatePropertiesContainer.propertyReferences.push(
@@ -596,6 +595,9 @@ module.exports = {
)
)
}
+ },
+ /** @param {Program} node */
+ 'Program:exit'(node) {
if (!node.templateBody) {
reportUnusedProperties()
}
diff --git a/lib/rules/prefer-separate-static-class.js b/lib/rules/prefer-separate-static-class.js
index 504d95d60..0ebeb2451 100644
--- a/lib/rules/prefer-separate-static-class.js
+++ b/lib/rules/prefer-separate-static-class.js
@@ -8,22 +8,11 @@
// Requirements
// ------------------------------------------------------------------------------
-const { defineTemplateBodyVisitor, getStringLiteralValue } = require('../utils')
-
-// ------------------------------------------------------------------------------
-// Helpers
-// ------------------------------------------------------------------------------
-
-/**
- * @param {ASTNode} node
- * @returns {node is Literal | TemplateLiteral}
- */
-function isStringLiteral(node) {
- return (
- (node.type === 'Literal' && typeof node.value === 'string') ||
- (node.type === 'TemplateLiteral' && node.expressions.length === 0)
- )
-}
+const {
+ defineTemplateBodyVisitor,
+ isStringLiteral,
+ getStringLiteralValue
+} = require('../utils')
/**
* @param {Expression | VForExpression | VOnExpression | VSlotScopeExpression | VFilterSequenceExpression} expressionNode
diff --git a/lib/utils/index.js b/lib/utils/index.js
index bacb892ba..69cd84a31 100644
--- a/lib/utils/index.js
+++ b/lib/utils/index.js
@@ -758,6 +758,17 @@ module.exports = {
}
},
+ /**
+ * @param {ASTNode} node
+ * @returns {node is Literal | TemplateLiteral}
+ */
+ isStringLiteral(node) {
+ return (
+ (node.type === 'Literal' && typeof node.value === 'string') ||
+ (node.type === 'TemplateLiteral' && node.expressions.length === 0)
+ )
+ },
+
/**
* Check whether the given node is a custom component or not.
* @param {VElement} node The start tag node to check.
diff --git a/package.json b/package.json
index 3ef950099..4579c6545 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "eslint-plugin-vue",
- "version": "8.4.0",
+ "version": "8.4.1",
"description": "Official ESLint plugin for Vue.js",
"main": "lib/index.js",
"scripts": {
diff --git a/tests/lib/rules/no-undef-components.js b/tests/lib/rules/no-undef-components.js
index 8bc637f45..b3a7af106 100644
--- a/tests/lib/rules/no-undef-components.js
+++ b/tests/lib/rules/no-undef-components.js
@@ -504,6 +504,19 @@ tester.run('no-undef-components', rule, {
`
},
+ {
+ filename: 'test.vue',
+ code: `
+
+
+
+
+ `
+ },
{
filename: 'test.vue',
code: `
diff --git a/tests/lib/rules/no-unused-properties.js b/tests/lib/rules/no-unused-properties.js
index 0023443cb..a75d83e72 100644
--- a/tests/lib/rules/no-unused-properties.js
+++ b/tests/lib/rules/no-unused-properties.js
@@ -4,7 +4,8 @@
*/
'use strict'
-const RuleTester = require('eslint').RuleTester
+const { RuleTester, Linter } = require('eslint')
+const assert = require('assert')
const rule = require('../../../lib/rules/no-unused-properties')
const tester = new RuleTester({
@@ -2805,3 +2806,42 @@ tester.run('no-unused-properties', rule, {
}
]
})
+
+// https://github.com/vuejs/eslint-plugin-vue/issues/1789
+describe('`vue/no-unused-properties` and `vue/no-unused-components` should not conflict.', () => {
+ const linter = new Linter()
+ linter.defineParser('vue-eslint-parser', require('vue-eslint-parser'))
+ linter.defineRule(
+ 'vue/no-unused-components',
+ require('../../../lib/rules/no-unused-components')
+ )
+ linter.defineRule('vue/no-unused-properties', rule)
+
+ const config = {
+ parser: 'vue-eslint-parser',
+ parserOptions: {
+ ecmaVersion: 2020,
+ sourceType: 'module'
+ },
+ rules: {
+ 'vue/no-unused-components': 'error',
+ 'vue/no-unused-properties': 'error'
+ }
+ }
+
+ it('should not be a false positive when using CSS v-bind().', () => {
+ const code = `
+
+
+ `
+ assert.deepStrictEqual(linter.verify(code, config, 'test.vue'), [])
+ })
+})
diff --git a/tools/update-docs-rules-index.js b/tools/update-docs-rules-index.js
index 913db1b91..9b177d7ac 100644
--- a/tools/update-docs-rules-index.js
+++ b/tools/update-docs-rules-index.js
@@ -38,7 +38,7 @@ function toRuleRow(rule) {
function toDeprecatedRuleRow(rule) {
const link = `[${rule.ruleId}](./${rule.name}.md)`
- const replacedRules = rule.meta.docs.replacedBy || []
+ const replacedRules = rule.meta.replacedBy || []
const replacedBy = replacedRules
.map((name) => `[vue/${name}](./${name}.md)`)
.join(', ')
diff --git a/tools/update-docs.js b/tools/update-docs.js
index 098585887..a7b847eee 100644
--- a/tools/update-docs.js
+++ b/tools/update-docs.js
@@ -120,8 +120,8 @@ class DocFile {
const notes = []
if (meta.deprecated) {
- if (meta.docs.replacedBy) {
- const replacedRules = meta.docs.replacedBy.map(
+ if (meta.replacedBy) {
+ const replacedRules = meta.replacedBy.map(
(name) => `[vue/${name}](${name}.md) rule`
)
notes.push(