Skip to content

Commit cd7f2e8

Browse files
authored
Merge branch 'master' into flow-53-hoc
2 parents 36c8aed + 35eb3ce commit cd7f2e8

18 files changed

+1163
-37
lines changed

.eslintrc

+4-4
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
"es6": true,
44
"node": true
55
},
6-
parserOptions: {
7-
ecmaVersion: 6,
8-
ecmaFeatures: {
9-
jsx: true
6+
"parserOptions": {
7+
"ecmaVersion": 6,
8+
"ecmaFeatures": {
9+
"jsx": true
1010
}
1111
},
1212
"rules": {

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ Finally, enable all of the rules that you would like to use. Use [our preset](#
142142
* [react/jsx-no-literals](docs/rules/jsx-no-literals.md): Prevent usage of unwrapped JSX strings
143143
* [react/jsx-no-target-blank](docs/rules/jsx-no-target-blank.md): Prevent usage of unsafe `target='_blank'`
144144
* [react/jsx-no-undef](docs/rules/jsx-no-undef.md): Disallow undeclared variables in JSX
145+
* [react/jsx-curly-brace-presence](docs/rules/jsx-curly-brace-presence.md): Enforce curly braces or disallow unnecessary curly braces in JSX
145146
* [react/jsx-pascal-case](docs/rules/jsx-pascal-case.md): Enforce PascalCase for user-defined JSX components
146147
* [react/jsx-sort-props](docs/rules/jsx-sort-props.md): Enforce props alphabetical sorting (fixable)
147148
* [react/jsx-space-before-closing](docs/rules/jsx-space-before-closing.md): Validate spacing before closing bracket in JSX (fixable)
+150
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
# Enforce curly braces or disallow unnecessary curly braces in JSX props and/or children. (react/jsx-curly-brace-presence)
2+
3+
This rule allows you to enforce curly braces or disallow unnecessary curly braces in JSX props and/or children.
4+
5+
For situations where JSX expressions are unnecessary, please refer to [the React doc](https://facebook.github.io/react/docs/jsx-in-depth.html) and [this page about JSX gotchas](https://github.com/facebook/react/blob/v15.4.0-rc.3/docs/docs/02.3-jsx-gotchas.md#html-entities).
6+
7+
**Fixable:** This rule is automatically fixable using the `--fix` flag on the command line
8+
9+
## Rule Details
10+
11+
By default, this rule will check for and warn about unnecessary curly braces in both JSX props and children.
12+
13+
You can pass in options to enforce the presence of curly braces on JSX props or children or both. The same options are available for not allowing unnecessary curly braces as well as ignoring the check.
14+
15+
## Rule Options
16+
17+
```js
18+
...
19+
"react/jsx-curly-brace-presence": [<enabled>, { "props": <string>, "children": <string> }]
20+
...
21+
```
22+
23+
or alternatively
24+
25+
```js
26+
...
27+
"react/jsx-curly-brace-presence": [<enabled>, <string>]
28+
...
29+
```
30+
31+
### Valid options for <string>
32+
33+
They are `always`, `never` and `ignore` for checking on JSX props and children.
34+
35+
* `always`: always enforce curly braces inside JSX props or/and children
36+
* `never`: never allow unnecessary curly braces inside JSX props or/and children
37+
* `ignore`: ignore the rule for JSX props or/and children
38+
39+
If passed in the option to fix, this is how a style violation will get fixed
40+
41+
* `always`: wrap a JSX attribute in curly braces/JSX expression and/or a JSX child the same way but also with double quotes
42+
* `never`: get rid of curly braces from a JSX attribute and/or a JSX child
43+
44+
- All fixing operations use double quotes.
45+
46+
For examples:
47+
48+
When `{ props: "always", children: "always" }` is set, the following patterns will be given warnings.
49+
50+
```jsx
51+
<App>Hello world</App>;
52+
<App prop='Hello world'>{'Hello world'}</App>;
53+
```
54+
55+
They can be fixed to:
56+
57+
```jsx
58+
<App>{"Hello world"}</App>;
59+
<App prop={"Hello world"}>{'Hello world'}</App>;
60+
```
61+
62+
When `{ props: "never", children: "never" }` is set, the following patterns will be given warnings.
63+
64+
```jsx
65+
<App>{'Hello world'}</App>;
66+
<App prop={'Hello world'} attr={"foo"} />;
67+
```
68+
69+
They can be fixed to:
70+
71+
```jsx
72+
<App>Hello world</App>;
73+
<App prop="Hello world" attr="foo" />;
74+
```
75+
76+
### Alternative syntax
77+
78+
The options are also `always`, `never` and `ignore` for the same meanings.
79+
80+
In this syntax, only a string is provided and the default will be set to that option for checking on both JSX props and children.
81+
82+
For examples:
83+
84+
When `'always'` is set, the following patterns will be given warnings.
85+
86+
```jsx
87+
<App>Hello world</App>;
88+
<App prop='Hello world' attr="foo">Hello world</App>;
89+
```
90+
91+
They can be fixed to:
92+
```jsx
93+
<App>{"Hello world"}</App>;
94+
<App prop={"Hello world"} attr={"foo"}>{"Hello world"}</App>;
95+
```
96+
97+
When `'never'` is set, the following pattern will be given warnings.
98+
99+
```jsx
100+
<App prop={'foo'} attr={"bar"}>{'Hello world'}</App>;
101+
```
102+
103+
It can fixed to:
104+
105+
```jsx
106+
<App prop="foo" attr="bar">Hello world</App>;
107+
```
108+
109+
## Edge cases
110+
111+
The fix also deals with template literals, strings with quotes, and strings with escapes characters.
112+
113+
* If the rule is set to get rid of unnecessary curly braces and the template literal inside a JSX expression has no expression, it will throw a warning and be fixed with double quotes. For example:
114+
115+
```jsx
116+
<App prop={`Hello world`}>{`Hello world`}</App>;
117+
```
118+
119+
will be warned and fixed to:
120+
121+
```jsx
122+
<App prop="Hello world">Hello world</App>;
123+
```
124+
125+
* If the rule is set to enforce curly braces and the strings have quotes, it will be fixed with double quotes for JSX children and the normal way for JSX attributes.
126+
127+
For example:
128+
129+
130+
```jsx
131+
<App prop='Hello "foo" world'>Hello 'foo' "bar" world</App>;
132+
```
133+
134+
will warned and fixed to:
135+
136+
```jsx
137+
<App prop={"Hello \"foo\" world"}>{"Hello 'foo' \"bar\" world"}</App>;
138+
```
139+
140+
* If the rule is set to get rid of unnecessary curly braces and the strings have escaped characters, it will not warn or fix for JSX children because JSX expressions are necessary in this case. For instance:
141+
142+
The following pattern will not be given a warning even if `'never'` is passed.
143+
144+
```jsx
145+
<App>{"Hello \u00b7 world"}</App>;
146+
```
147+
148+
## When Not To Use It
149+
150+
You should turn this rule off if you are not concerned about maintaining consistency regarding the use of curly braces in JSX props and/or children as well as the use of unnecessary JSX expressions.

docs/rules/sort-comp.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Enforce component methods order (react/sort-comp)
22

3-
When creating React components it is more convenient to always follow the same organisation for methods order to helps you to easily find lifecyle methods, event handlers, etc.
3+
When creating React components it is more convenient to always follow the same organisation for method order to help you easily find lifecyle methods, event handlers, etc.
44

55
**Fixable:** This rule is automatically fixable using the [`sort-comp` transform](https://github.com/reactjs/react-codemod/blob/master/transforms/sort-comp.js) in [react-codemod](https://www.npmjs.com/package/react-codemod).
66

index.js

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ const allRules = {
2828
'jsx-no-literals': require('./lib/rules/jsx-no-literals'),
2929
'jsx-no-target-blank': require('./lib/rules/jsx-no-target-blank'),
3030
'jsx-no-undef': require('./lib/rules/jsx-no-undef'),
31+
'jsx-curly-brace-presence': require('./lib/rules/jsx-curly-brace-presence'),
3132
'jsx-pascal-case': require('./lib/rules/jsx-pascal-case'),
3233
'jsx-sort-props': require('./lib/rules/jsx-sort-props'),
3334
'jsx-space-before-closing': require('./lib/rules/jsx-space-before-closing'),

lib/rules/boolean-prop-naming.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ module.exports = {
118118
const component = components.get(node) || node;
119119
const invalidProps = component.invalidProps || [];
120120

121-
proptypes.forEach(prop => {
121+
(proptypes || []).forEach(prop => {
122122
const propKey = getPropKey(prop);
123123
const flowCheck = (
124124
prop.type === 'ObjectTypeProperty' &&

lib/rules/default-props-match-prop-types.js

+27-5
Original file line numberDiff line numberDiff line change
@@ -163,23 +163,46 @@ module.exports = {
163163
}));
164164
}
165165

166+
/**
167+
* Handles Props defined in IntersectionTypeAnnotation nodes
168+
* e.g. type Props = PropsA & PropsB
169+
* @param {ASTNode} intersectionTypeAnnotation ObjectExpression node.
170+
* @returns {Object[]}
171+
*/
172+
function getPropertiesFromIntersectionTypeAnnotationNode(annotation) {
173+
return annotation.types.reduce((properties, type) => {
174+
annotation = resolveGenericTypeAnnotation(type);
175+
176+
if (annotation && annotation.id) {
177+
annotation = findVariableByName(annotation.id.name);
178+
}
179+
180+
return properties.concat(annotation.properties);
181+
}, []);
182+
}
183+
166184
/**
167185
* Extracts a PropType from a TypeAnnotation node.
168186
* @param {ASTNode} node TypeAnnotation node.
169187
* @returns {Object[]} Array of PropType object representations, to be consumed by `addPropTypesToComponent`.
170188
*/
171189
function getPropTypesFromTypeAnnotation(node) {
172-
let properties;
190+
let properties = [];
173191

174192
switch (node.typeAnnotation.type) {
175193
case 'GenericTypeAnnotation':
176194
let annotation = resolveGenericTypeAnnotation(node.typeAnnotation);
177195

178-
if (annotation && annotation.id) {
179-
annotation = findVariableByName(annotation.id.name);
196+
if (annotation && annotation.type === 'IntersectionTypeAnnotation') {
197+
properties = getPropertiesFromIntersectionTypeAnnotationNode(annotation);
198+
} else {
199+
if (annotation && annotation.id) {
200+
annotation = findVariableByName(annotation.id.name);
201+
}
202+
203+
properties = annotation ? (annotation.properties || []) : [];
180204
}
181205

182-
properties = annotation ? (annotation.properties || []) : [];
183206
break;
184207

185208
case 'UnionTypeAnnotation':
@@ -314,7 +337,6 @@ module.exports = {
314337
if (!component) {
315338
return;
316339
}
317-
318340
addPropTypesToComponent(component, getPropTypesFromTypeAnnotation(node.typeAnnotation, context));
319341
}
320342

0 commit comments

Comments
 (0)