From 9ca878fd6709390d318cf4d74e7640c3c33ccbe1 Mon Sep 17 00:00:00 2001 From: Luke Bennett Date: Thu, 15 Aug 2019 17:29:39 +0100 Subject: [PATCH 1/2] New: Add `vue/name-property-required` rule --- lib/rules/name-property-required.js | 44 +++++++++++ tests/lib/rules/name-property-required.js | 96 +++++++++++++++++++++++ 2 files changed, 140 insertions(+) create mode 100644 lib/rules/name-property-required.js create mode 100644 tests/lib/rules/name-property-required.js diff --git a/lib/rules/name-property-required.js b/lib/rules/name-property-required.js new file mode 100644 index 000000000..b0235dbbb --- /dev/null +++ b/lib/rules/name-property-required.js @@ -0,0 +1,44 @@ +/** + * @fileoverview Require a name property in Vue components + * @author LukeeeeBennett + */ +'use strict' + +const utils = require('../utils') + +function isNameProperty (node) { + return node.type === 'Property' && node.key.name === 'name' +} + +function hasTruthyLiteralValue (node) { + return node.value.type === 'Literal' && node.value.value +} + +module.exports = { + meta: { + type: 'suggestion', + docs: { + description: 'require a name property in Vue components', + category: undefined, + url: 'https://eslint.vuejs.org/rules/name-property-required.html' + }, + fixable: null, + schema: [] + }, + + create (context) { + return utils.executeOnVue(context, component => { + const isValid = component.properties.some(property => { + return isNameProperty(property) && + hasTruthyLiteralValue(property) + }) + + if (isValid) return + + context.report({ + node: component, + message: 'Required name property is undefined.' + }) + }) + } +} diff --git a/tests/lib/rules/name-property-required.js b/tests/lib/rules/name-property-required.js new file mode 100644 index 000000000..15cc1fe80 --- /dev/null +++ b/tests/lib/rules/name-property-required.js @@ -0,0 +1,96 @@ +/** + * @fileoverview Require a name property in Vue components + * @author LukeeeeBennett + */ +'use strict' + +const rule = require('../../../lib/rules/name-property-required') +const RuleTester = require('eslint').RuleTester + +const parserOptions = { + ecmaVersion: 2018, + sourceType: 'module' +} + +const ruleTester = new RuleTester() +ruleTester.run('name-property-required', rule, { + + valid: [ + { + filename: 'ValidComponent.vue', + code: ` + export default { + name: 'IssaName' + } + `, + parserOptions + } + ], + + invalid: [ + { + filename: 'InvalidComponent.vue', + code: ` + export default { + } + `, + parserOptions, + errors: [{ + message: 'Required name property is undefined.', + type: 'ObjectExpression' + }] + }, + { + filename: 'InvalidComponent.vue', + code: ` + export default { + nameNot: 'IssaNameNot' + } + `, + parserOptions, + errors: [{ + message: 'Required name property is undefined.', + type: 'ObjectExpression' + }] + }, + { + filename: 'InvalidComponent.vue', + code: ` + export default { + name: '' + } + `, + parserOptions, + errors: [{ + message: 'Required name property is undefined.', + type: 'ObjectExpression' + }] + }, + { + filename: 'InvalidComponent.vue', + code: ` + export default { + name: undefined + } + `, + parserOptions, + errors: [{ + message: 'Required name property is undefined.', + type: 'ObjectExpression' + }] + }, + { + filename: 'InvalidComponent.vue', + code: ` + export default { + name: null + } + `, + parserOptions, + errors: [{ + message: 'Required name property is undefined.', + type: 'ObjectExpression' + }] + } + ] +}) From 964475aadcb4daafd9e08c7919fe8e7268b3d6d6 Mon Sep 17 00:00:00 2001 From: Luke Bennett Date: Wed, 4 Sep 2019 09:48:20 +0100 Subject: [PATCH 2/2] Rename to `require-name-property`, remove literal value assertion, add docs --- docs/rules/require-name-property.md | 43 +++++++++++++++++ ...y-required.js => require-name-property.js} | 19 +++----- ...y-required.js => require-name-property.js} | 48 +++++++++++-------- 3 files changed, 76 insertions(+), 34 deletions(-) create mode 100644 docs/rules/require-name-property.md rename lib/rules/{name-property-required.js => require-name-property.js} (52%) rename tests/lib/rules/{name-property-required.js => require-name-property.js} (68%) diff --git a/docs/rules/require-name-property.md b/docs/rules/require-name-property.md new file mode 100644 index 000000000..7217cb52d --- /dev/null +++ b/docs/rules/require-name-property.md @@ -0,0 +1,43 @@ +--- +pageClass: rule-details +sidebarDepth: 0 +title: vue/require-name-property +description: require a component name property +--- +# vue/require-name-property +> require a component name property + +## :book: Rule Details + +This rule requires a `name` property to be set on components. + + + +```vue + +``` + + + +## :wrench: Options + +Nothing. + +## :mag: Implementation + +- [Rule source](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/require-name-property.js) +- [Test source](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/require-name-property.js) diff --git a/lib/rules/name-property-required.js b/lib/rules/require-name-property.js similarity index 52% rename from lib/rules/name-property-required.js rename to lib/rules/require-name-property.js index b0235dbbb..126c1bfe6 100644 --- a/lib/rules/name-property-required.js +++ b/lib/rules/require-name-property.js @@ -7,11 +7,9 @@ const utils = require('../utils') function isNameProperty (node) { - return node.type === 'Property' && node.key.name === 'name' -} - -function hasTruthyLiteralValue (node) { - return node.value.type === 'Literal' && node.value.value + return node.type === 'Property' && + node.key.name === 'name' && + !node.computed } module.exports = { @@ -20,7 +18,7 @@ module.exports = { docs: { description: 'require a name property in Vue components', category: undefined, - url: 'https://eslint.vuejs.org/rules/name-property-required.html' + url: 'https://eslint.vuejs.org/rules/require-name-property.html' }, fixable: null, schema: [] @@ -28,16 +26,11 @@ module.exports = { create (context) { return utils.executeOnVue(context, component => { - const isValid = component.properties.some(property => { - return isNameProperty(property) && - hasTruthyLiteralValue(property) - }) - - if (isValid) return + if (component.properties.some(isNameProperty)) return context.report({ node: component, - message: 'Required name property is undefined.' + message: 'Required name property is not set.' }) }) } diff --git a/tests/lib/rules/name-property-required.js b/tests/lib/rules/require-name-property.js similarity index 68% rename from tests/lib/rules/name-property-required.js rename to tests/lib/rules/require-name-property.js index 15cc1fe80..7b55e2400 100644 --- a/tests/lib/rules/name-property-required.js +++ b/tests/lib/rules/require-name-property.js @@ -4,7 +4,7 @@ */ 'use strict' -const rule = require('../../../lib/rules/name-property-required') +const rule = require('../../../lib/rules/require-name-property') const RuleTester = require('eslint').RuleTester const parserOptions = { @@ -13,8 +13,7 @@ const parserOptions = { } const ruleTester = new RuleTester() -ruleTester.run('name-property-required', rule, { - +ruleTester.run('require-name-property', rule, { valid: [ { filename: 'ValidComponent.vue', @@ -24,32 +23,37 @@ ruleTester.run('name-property-required', rule, { } `, parserOptions - } - ], - - invalid: [ + }, { - filename: 'InvalidComponent.vue', + filename: 'ValidComponent.vue', code: ` export default { + name: undefined } `, - parserOptions, - errors: [{ - message: 'Required name property is undefined.', - type: 'ObjectExpression' - }] + parserOptions }, + { + filename: 'ValidComponent.vue', + code: ` + export default { + name: '' + } + `, + parserOptions + } + ], + + invalid: [ { filename: 'InvalidComponent.vue', code: ` export default { - nameNot: 'IssaNameNot' } `, parserOptions, errors: [{ - message: 'Required name property is undefined.', + message: 'Required name property is not set.', type: 'ObjectExpression' }] }, @@ -57,12 +61,12 @@ ruleTester.run('name-property-required', rule, { filename: 'InvalidComponent.vue', code: ` export default { - name: '' + nameNot: 'IssaNameNot' } `, parserOptions, errors: [{ - message: 'Required name property is undefined.', + message: 'Required name property is not set.', type: 'ObjectExpression' }] }, @@ -70,12 +74,14 @@ ruleTester.run('name-property-required', rule, { filename: 'InvalidComponent.vue', code: ` export default { - name: undefined + computed: { + name() { return 'name' } + } } `, parserOptions, errors: [{ - message: 'Required name property is undefined.', + message: 'Required name property is not set.', type: 'ObjectExpression' }] }, @@ -83,12 +89,12 @@ ruleTester.run('name-property-required', rule, { filename: 'InvalidComponent.vue', code: ` export default { - name: null + [name]: 'IssaName' } `, parserOptions, errors: [{ - message: 'Required name property is undefined.', + message: 'Required name property is not set.', type: 'ObjectExpression' }] }