Skip to content

Commit e31b735

Browse files
committed
Merge pull request #306 from jakemmarsh/jsx-pascal-case
Add jsx-pascal-case rule
2 parents ac59d8d + 9d07f1d commit e31b735

File tree

5 files changed

+159
-0
lines changed

5 files changed

+159
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ Finally, enable all of the rules that you would like to use.
9595
* [jsx-no-duplicate-props](docs/rules/jsx-no-duplicate-props.md): Prevent duplicate props in JSX
9696
* [jsx-no-literals](docs/rules/jsx-no-literals.md): Prevent usage of unwrapped JSX strings
9797
* [jsx-no-undef](docs/rules/jsx-no-undef.md): Disallow undeclared variables in JSX
98+
* [jsx-pascal-case](docs/rules/jsx-pascal-case.md): Enforce PascalCase for user-defined JSX components
9899
* [jsx-quotes](docs/rules/jsx-quotes.md): Enforce quote style for JSX attributes
99100
* [jsx-sort-prop-types](docs/rules/jsx-sort-prop-types.md): Enforce propTypes declarations alphabetical sorting
100101
* [jsx-sort-props](docs/rules/jsx-sort-props.md): Enforce props alphabetical sorting

docs/rules/jsx-pascal-case.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Enforce PasalCase for user-defined JSX components (jsx-pascal-case)
2+
3+
Enforces coding style that user-defined JSX components are defined and referenced in PascalCase.
4+
5+
## Rule Details
6+
7+
The following patterns are considered warnings:
8+
9+
```js
10+
<testComponent />
11+
```
12+
13+
```js
14+
<testComponent>
15+
<div />
16+
</testComponent>
17+
```
18+
19+
```js
20+
<test_component />
21+
```
22+
23+
The following patterns are not considered warnings:
24+
25+
```js
26+
<TestComponent />
27+
```
28+
29+
```js
30+
<TestComponent>
31+
<div />
32+
</TestComponent>
33+
```
34+
35+
## When Not To Use It
36+
37+
If you are not using JSX.

index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ module.exports = {
1414
'no-did-update-set-state': require('./lib/rules/no-did-update-set-state'),
1515
'react-in-jsx-scope': require('./lib/rules/react-in-jsx-scope'),
1616
'jsx-uses-vars': require('./lib/rules/jsx-uses-vars'),
17+
'jsx-pascal-case': require('./lib/rules/jsx-pascal-case'),
1718
'jsx-no-bind': require('./lib/rules/jsx-no-bind'),
1819
'jsx-no-undef': require('./lib/rules/jsx-no-undef'),
1920
'jsx-quotes': require('./lib/rules/jsx-quotes'),
@@ -47,6 +48,7 @@ module.exports = {
4748
'no-did-update-set-state': 0,
4849
'react-in-jsx-scope': 0,
4950
'jsx-uses-vars': 1,
51+
'jsx-pascal-case': 0,
5052
'jsx-no-bind': 0,
5153
'jsx-no-undef': 0,
5254
'jsx-quotes': 0,

lib/rules/jsx-pascal-case.js

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/**
2+
* @fileoverview Enforce PasalCase for user-defined JSX components
3+
* @author Jake Marsh
4+
*/
5+
6+
'use strict';
7+
8+
var variableUtil = require('../util/variable');
9+
10+
// ------------------------------------------------------------------------------
11+
// Constants
12+
// ------------------------------------------------------------------------------
13+
14+
var PASCAL_CASE_REGEX = /^[A-Z][a-z]+(?:[A-Z][a-z]+)*$/;
15+
16+
// ------------------------------------------------------------------------------
17+
// Rule Definition
18+
// ------------------------------------------------------------------------------
19+
20+
module.exports = function(context) {
21+
22+
return {
23+
JSXOpeningElement: function(node) {
24+
var variables = variableUtil.variablesInScope(context);
25+
26+
switch (node.name.type) {
27+
case 'JSXIdentifier':
28+
node = node.name;
29+
break;
30+
case 'JSXMemberExpression':
31+
node = node.name.object;
32+
break;
33+
case 'JSXNamespacedName':
34+
node = node.name.namespace;
35+
break;
36+
default:
37+
break;
38+
}
39+
40+
var isImportedVariable = variableUtil.findVariable(variables, node.name);
41+
var isPascalCase = PASCAL_CASE_REGEX.test(node.name);
42+
43+
if (isImportedVariable && !isPascalCase) {
44+
context.report(node, 'Imported JSX component ' + node.name + ' must be in PascalCase');
45+
}
46+
}
47+
};
48+
49+
};

tests/lib/rules/jsx-pascal-case.js

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/**
2+
* @fileoverview Tests for jsx-pascal-case
3+
* @author Jake Marsh
4+
*/
5+
'use strict';
6+
7+
// ------------------------------------------------------------------------------
8+
// Requirements
9+
// ------------------------------------------------------------------------------
10+
11+
var rule = require('../../../lib/rules/jsx-pascal-case');
12+
var RuleTester = require('eslint').RuleTester;
13+
14+
// ------------------------------------------------------------------------------
15+
// Tests
16+
// ------------------------------------------------------------------------------
17+
18+
var ruleTester = new RuleTester();
19+
ruleTester.run('jsx-pascal-case', rule, {
20+
valid: [{
21+
code: [
22+
'var TestComponent;',
23+
'<TestComponent />'
24+
].join('\n'),
25+
ecmaFeatures: {
26+
jsx: true
27+
}
28+
}, {
29+
code: [
30+
'var TestComponent;',
31+
'<TestComponent>',
32+
' <div />',
33+
'</TestComponent>'
34+
].join('\n'),
35+
ecmaFeatures: {
36+
jsx: true
37+
}
38+
}],
39+
40+
invalid: [{
41+
code: [
42+
'var testComponent;',
43+
'<testComponent />'
44+
].join('\n'),
45+
ecmaFeatures: {
46+
jsx: true
47+
},
48+
errors: [{message: 'Imported JSX component testComponent must be in PascalCase'}]
49+
}, {
50+
code: [
51+
'var test_component;',
52+
'<test_component />'
53+
].join('\n'),
54+
ecmaFeatures: {
55+
jsx: true
56+
},
57+
errors: [{message: 'Imported JSX component test_component must be in PascalCase'}]
58+
}, {
59+
code: [
60+
'var testComponent;',
61+
'<testComponent>',
62+
' <div />',
63+
'</testComponent>'
64+
].join('\n'),
65+
ecmaFeatures: {
66+
jsx: true
67+
},
68+
errors: [{message: 'Imported JSX component testComponent must be in PascalCase'}]
69+
}]
70+
});

0 commit comments

Comments
 (0)