diff --git a/index.js b/index.js index 9ba7f1e5e3..ad33d96eb1 100644 --- a/index.js +++ b/index.js @@ -23,6 +23,7 @@ module.exports = { 'jsx-quotes': require('./lib/rules/jsx-quotes'), 'no-unknown-property': require('./lib/rules/no-unknown-property'), 'jsx-curly-spacing': require('./lib/rules/jsx-curly-spacing'), + 'jsx-equals-spacing': require('./lib/rules/jsx-equals-spacing'), 'jsx-sort-props': require('./lib/rules/jsx-sort-props'), 'jsx-sort-prop-types': require('./lib/rules/jsx-sort-prop-types'), 'jsx-boolean-value': require('./lib/rules/jsx-boolean-value'), @@ -62,6 +63,7 @@ module.exports = { 'jsx-quotes': 0, 'no-unknown-property': 0, 'jsx-curly-spacing': 0, + 'jsx-equals-spacing': 0, 'jsx-sort-props': 0, 'jsx-sort-prop-types': 0, 'jsx-boolean-value': 0, diff --git a/lib/rules/jsx-equals-spacing.js b/lib/rules/jsx-equals-spacing.js new file mode 100644 index 0000000000..7773c10381 --- /dev/null +++ b/lib/rules/jsx-equals-spacing.js @@ -0,0 +1,69 @@ +/** + * @fileoverview Disallow or enforce spaces around equal signs in JSX attributes. + * @author ryym + */ +'use strict'; + +// ------------------------------------------------------------------------------ +// Rule Definition +// ------------------------------------------------------------------------------ + +module.exports = function(context) { + var config = context.options[0]; + var sourceCode = context.getSourceCode(); + + /** + * Determines a given attribute node has an equal sign. + * @param {ASTNode} attrNode - The attribute node. + * @returns {boolean} Whether or not the attriute node has an equal sign. + */ + function hasEqual(attrNode) { + return attrNode.type !== 'JSXSpreadAttribute' && attrNode.value !== null; + } + + // -------------------------------------------------------------------------- + // Public + // -------------------------------------------------------------------------- + + return { + JSXOpeningElement: function(node) { + node.attributes.forEach(function(attrNode) { + if (!hasEqual(attrNode)) { + return; + } + + var equalToken = sourceCode.getTokenAfter(attrNode.name); + var spacedBefore = sourceCode.isSpaceBetweenTokens(attrNode.name, equalToken); + var spacedAfter = sourceCode.isSpaceBetweenTokens(equalToken, attrNode.value); + + switch (config) { + default: + case 'never': + if (spacedBefore) { + context.report(attrNode, equalToken.loc.start, + 'There should be no space before \'=\''); + } + if (spacedAfter) { + context.report(attrNode, equalToken.loc.start, + 'There should be no space after \'=\''); + } + break; + case 'always': + if (!spacedBefore) { + context.report(attrNode, equalToken.loc.start, + 'A space is required before \'=\''); + } + if (!spacedAfter) { + context.report(attrNode, equalToken.loc.start, + 'A space is required after \'=\''); + } + break; + } + }); + } + }; +}; + +module.exports.schema = [{ + enum: ['always', 'never'] +}]; diff --git a/tests/lib/rules/jsx-equals-spacing.js b/tests/lib/rules/jsx-equals-spacing.js new file mode 100644 index 0000000000..dce47af12d --- /dev/null +++ b/tests/lib/rules/jsx-equals-spacing.js @@ -0,0 +1,154 @@ +/** + * @fileoverview Disallow or enforce spaces around equal signs in JSX attributes. + * @author ryym + */ +'use strict'; + +// ------------------------------------------------------------------------------ +// Requirements +// ------------------------------------------------------------------------------ + +var rule = require('../../../lib/rules/jsx-equals-spacing'); +var RuleTester = require('eslint').RuleTester; + +var parserOptions = { + ecmaVersion: 6, + ecmaFeatures: { + jsx: true + } +}; + +// ------------------------------------------------------------------------------ +// Tests +// ------------------------------------------------------------------------------ + +var ruleTester = new RuleTester(); +ruleTester.run('jsx-equals-spacing', rule, { + valid: [{ + code: '', + parserOptions: parserOptions + }, { + code: '', + parserOptions: parserOptions + }, { + code: '', + parserOptions: parserOptions + }, { + code: ' bar(e)} />', + parserOptions: parserOptions + }, { + code: '', + parserOptions: parserOptions + }, { + code: '', + options: ['never'], + parserOptions: parserOptions + }, { + code: '', + options: ['never'], + parserOptions: parserOptions + }, { + code: '', + options: ['never'], + parserOptions: parserOptions + }, { + code: ' bar(e)} />', + options: ['never'], + parserOptions: parserOptions + }, { + code: '', + options: ['never'], + parserOptions: parserOptions + }, { + code: '', + options: ['always'], + parserOptions: parserOptions + }, { + code: '', + options: ['always'], + parserOptions: parserOptions + }, { + code: '', + options: ['always'], + parserOptions: parserOptions + }, { + code: ' bar(e)} />', + options: ['always'], + parserOptions: parserOptions + }, { + code: '', + options: ['always'], + parserOptions: parserOptions + }], + + invalid: [{ + code: '', + parserOptions: parserOptions, + errors: [ + {message: 'There should be no space before \'=\''}, + {message: 'There should be no space after \'=\''} + ] + }, { + code: '', + options: ['never'], + parserOptions: parserOptions, + errors: [ + {message: 'There should be no space before \'=\''}, + {message: 'There should be no space after \'=\''} + ] + }, { + code: '', + options: ['never'], + parserOptions: parserOptions, + errors: [ + {message: 'There should be no space before \'=\''} + ] + }, { + code: '', + options: ['never'], + parserOptions: parserOptions, + errors: [ + {message: 'There should be no space after \'=\''} + ] + }, { + code: '', + options: ['never'], + parserOptions: parserOptions, + errors: [ + {message: 'There should be no space after \'=\''}, + {message: 'There should be no space before \'=\''}, + {message: 'There should be no space after \'=\''} + ] + }, { + code: '', + options: ['always'], + parserOptions: parserOptions, + errors: [ + {message: 'A space is required before \'=\''}, + {message: 'A space is required after \'=\''} + ] + }, { + code: '', + options: ['always'], + parserOptions: parserOptions, + errors: [ + {message: 'A space is required after \'=\''} + ] + }, { + code: '', + options: ['always'], + parserOptions: parserOptions, + errors: [ + {message: 'A space is required before \'=\''} + ] + }, { + code: '', + options: ['always'], + parserOptions: parserOptions, + errors: [ + {message: 'A space is required before \'=\''}, + {message: 'A space is required after \'=\''}, + {message: 'A space is required after \'=\''} + ] + }] +});