Skip to content

Commit f9ea195

Browse files
mathieumgyannickcr
authored andcommitted
Add shorthandFirst option to jsx-sort-props (fixes #391)
1 parent eb872c9 commit f9ea195

File tree

3 files changed

+60
-6
lines changed

3 files changed

+60
-6
lines changed

docs/rules/jsx-sort-props.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ The following patterns are considered okay and do not cause warnings:
2626
"jsx-sort-props": [<enabled>, {
2727
"callbacksLast": <boolean>,
2828
"shorthandFirst": <boolean>,
29+
"shorthandLast": <boolean>,
2930
"ignoreCase": <boolean>
3031
}]
3132
...
@@ -43,7 +44,7 @@ The following patterns are considered okay and do not cause warnings:
4344

4445
### `callbacksLast`
4546

46-
When `true`, callbacks must be listed after all other props:
47+
When `true`, callbacks must be listed after all other props, even if `shorthandLast` is set :
4748

4849
```js
4950
<Hello tel={5555555} onClick={this._handleClick} />
@@ -57,6 +58,14 @@ When `true`, short hand props must be listed before all other props, but still r
5758
<Hello active validate name="John" tel={5555555} />
5859
```
5960

61+
### `shorthandLast`
62+
63+
When `true`, short hand props must be listed after all other props (unless `callbacksLast` is set), but still respecting the alphabetical order:
64+
65+
```js
66+
<Hello name="John" tel={5555555} active validate />
67+
```
68+
6069
## When not to use
6170

6271
This rule is a formatting preference and not following it won't negatively affect the quality of your code. If alphabetizing props isn't a part of your coding standards, then you can leave this rule off.

lib/rules/jsx-sort-props.js

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ module.exports = function(context) {
2020
var ignoreCase = configuration.ignoreCase || false;
2121
var callbacksLast = configuration.callbacksLast || false;
2222
var shorthandFirst = configuration.shorthandFirst || false;
23+
var shorthandLast = configuration.shorthandLast || false;
2324

2425
return {
2526
JSXOpeningElement: function(node) {
@@ -68,6 +69,19 @@ module.exports = function(context) {
6869
}
6970
}
7071

72+
if (shorthandLast) {
73+
if (!currentValue && previousValue) {
74+
return decl;
75+
}
76+
if (currentValue && !previousValue) {
77+
context.report({
78+
node: memo,
79+
message: 'Shorthand props must be listed after all other props'
80+
});
81+
return memo;
82+
}
83+
}
84+
7185
if (currentPropName < previousPropName) {
7286
context.report({
7387
node: decl,
@@ -86,14 +100,18 @@ module.exports.schema = [{
86100
type: 'object',
87101
properties: {
88102
// Whether callbacks (prefixed with "on") should be listed at the very end,
89-
// after all other props.
103+
// after all other props. Supersedes shorthandLast.
90104
callbacksLast: {
91105
type: 'boolean'
92106
},
93107
// Whether shorthand properties (without a value) should be listed first
94108
shorthandFirst: {
95109
type: 'boolean'
96110
},
111+
// Whether shorthand properties (without a value) should be listed last
112+
shorthandLast: {
113+
type: 'boolean'
114+
},
97115
ignoreCase: {
98116
type: 'boolean'
99117
}

tests/lib/rules/jsx-sort-props.js

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,27 @@ var expectedCallbackError = {
3333
message: 'Callbacks must be listed after all other props',
3434
type: 'JSXAttribute'
3535
};
36-
var expectedShorthandError = {
36+
var expectedShorthandFirstError = {
3737
message: 'Shorthand props must be listed before all other props',
3838
type: 'JSXAttribute'
3939
};
40+
var expectedShorthandLastError = {
41+
message: 'Shorthand props must be listed after all other props',
42+
type: 'JSXAttribute'
43+
};
4044
var callbacksLastArgs = [{
4145
callbacksLast: true
4246
}];
4347
var shorthandFirstArgs = [{
4448
shorthandFirst: true
4549
}];
50+
var shorthandLastArgs = [{
51+
shorthandLast: true
52+
}];
53+
var shorthandAndCallbackLastArgs = [{
54+
callbacksLast: true,
55+
shorthandLast: true
56+
}];
4657
var ignoreCaseArgs = [{
4758
ignoreCase: true
4859
}];
@@ -67,7 +78,13 @@ ruleTester.run('jsx-sort-props', rule, {
6778
// Sorting shorthand props before others
6879
{code: '<App a b="b" />;', options: shorthandFirstArgs, parserOptions: parserOptions},
6980
{code: '<App z a="a" />;', options: shorthandFirstArgs, parserOptions: parserOptions},
70-
{code: '<App x y z a="a" b="b" />;', options: shorthandFirstArgs, parserOptions: parserOptions}
81+
{code: '<App x y z a="a" b="b" />;', options: shorthandFirstArgs, parserOptions: parserOptions},
82+
{code: '<App a="a" b="b" x y z />;', options: shorthandLastArgs, parserOptions: parserOptions},
83+
{
84+
code: '<App a="a" b="b" x y z onBar onFoo />;',
85+
options: shorthandAndCallbackLastArgs,
86+
parserOptions: parserOptions
87+
}
7188
],
7289
invalid: [
7390
{code: '<App b a />;', errors: [expectedError], parserOptions: parserOptions},
@@ -91,10 +108,20 @@ ruleTester.run('jsx-sort-props', rule, {
91108
parserOptions: parserOptions
92109
}, {
93110
code: '<App a="a" b />;',
94-
errors: [expectedShorthandError],
111+
errors: [expectedShorthandFirstError],
95112
options: shorthandFirstArgs,
96113
parserOptions: parserOptions
97114
},
98-
{code: '<App z x a="a" />;', errors: [expectedError], options: shorthandFirstArgs, parserOptions: parserOptions}
115+
{code: '<App z x a="a" />;', errors: [expectedError], options: shorthandFirstArgs, parserOptions: parserOptions}, {
116+
code: '<App b a="a" />;',
117+
errors: [expectedShorthandLastError],
118+
options: shorthandLastArgs,
119+
parserOptions: parserOptions
120+
}, {
121+
code: '<App a="a" onBar onFoo z x />;',
122+
errors: [shorthandAndCallbackLastArgs],
123+
options: shorthandLastArgs,
124+
parserOptions: parserOptions
125+
}
99126
]
100127
});

0 commit comments

Comments
 (0)