Skip to content

Commit

Permalink
Merge pull request #161 from hummlas/no-dupe-props
Browse files Browse the repository at this point in the history
Add jsx-no-duplicate-props rule (fixes #143)
  • Loading branch information
yannickcr committed Jul 20, 2015
2 parents 7a62fde + 0dbd28c commit 1ca6062
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 2 deletions.
6 changes: 4 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ module.exports = {
'jsx-sort-prop-types': require('./lib/rules/jsx-sort-prop-types'),
'jsx-boolean-value': require('./lib/rules/jsx-boolean-value'),
'sort-comp': require('./lib/rules/sort-comp'),
'require-extension': require('./lib/rules/require-extension')
'require-extension': require('./lib/rules/require-extension'),
'jsx-no-duplicate-props': require('./lib/rules/jsx-no-duplicate-props')
},
rulesConfig: {
'jsx-uses-react': 0,
Expand All @@ -43,6 +44,7 @@ module.exports = {
'jsx-sort-prop-types': 0,
'jsx-boolean-value': 0,
'sort-comp': 0,
'require-extension': 0
'require-extension': 0,
'jsx-no-duplicate-props': 0
}
};
50 changes: 50 additions & 0 deletions lib/rules/jsx-no-duplicate-props.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/**
* @fileoverview Enforce no duplicate props
* @author Markus Ånöstam
*/

'use strict';

// ------------------------------------------------------------------------------
// Rule Definition
// ------------------------------------------------------------------------------

module.exports = function (context) {

var configuration = context.options[0] || {};
var ignoreCase = configuration.ignoreCase || false;

return {
JSXOpeningElement: function (node) {
var props = {};

node.attributes.forEach(function(decl) {
if (decl.type === 'JSXSpreadAttribute') {
return;
}

var name = decl.name.name;

if (ignoreCase) {
name = name.toLowerCase();
}

if (props.hasOwnProperty(name)) {
context.report(decl, 'No duplicate props allowed');
} else {
props[name] = 1;
}
});
}
};
};

module.exports.schema = [{
type: 'object',
properties: {
ignoreCase: {
type: 'boolean'
}
},
additionalProperties: false
}];
57 changes: 57 additions & 0 deletions tests/lib/rules/jsx-no-duplicate-props.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/**
* @fileoverview Enforce no duplicate props
* @author Markus Ånöstam
*/

'use strict';

// -----------------------------------------------------------------------------
// Requirements
// -----------------------------------------------------------------------------

var eslint = require('eslint').linter;
var ESLintTester = require('eslint-tester');

// -----------------------------------------------------------------------------
// Tests
// -----------------------------------------------------------------------------

var eslintTester = new ESLintTester(eslint);

var expectedError = {
message: 'No duplicate props allowed',
type: 'JSXAttribute'
};

var ignoreCaseArgs = [1, {
ignoreCase: true
}];

var features = {
jsx: true
};

eslintTester.addRuleTest('lib/rules/jsx-no-duplicate-props', {
valid: [
{code: '<App />;', ecmaFeatures: features},
{code: '<App {...this.props} />;', ecmaFeatures: features},
{code: '<App a b c />;', ecmaFeatures: features},
{code: '<App a b c A />;', ecmaFeatures: features},
{code: '<App {...this.props} a b c />;', ecmaFeatures: features},
{code: '<App c {...this.props} a b />;', ecmaFeatures: features},
{code: '<App a="c" b="b" c="a" />;', ecmaFeatures: features},
{code: '<App {...this.props} a="c" b="b" c="a" />;', ecmaFeatures: features},
{code: '<App c="a" {...this.props} a="c" b="b" />;', ecmaFeatures: features},
{code: '<App A a />;', ecmaFeatures: features},
{code: '<App A b a />;', ecmaFeatures: features},
{code: '<App A="a" b="b" B="B" />;', ecmaFeatures: features}
],
invalid: [
{code: '<App a a />;', errors: [expectedError], ecmaFeatures: features},
{code: '<App A b c A />;', errors: [expectedError], ecmaFeatures: features},
{code: '<App a="a" b="b" a="a" />;', errors: [expectedError], ecmaFeatures: features},
{code: '<App A a />;', args: ignoreCaseArgs, errors: [expectedError], ecmaFeatures: features},
{code: '<App a b c A />;', args: ignoreCaseArgs, errors: [expectedError], ecmaFeatures: features},
{code: '<App A="a" b="b" B="B" />;', args: ignoreCaseArgs, errors: [expectedError], ecmaFeatures: features}
]
});

0 comments on commit 1ca6062

Please sign in to comment.