diff --git a/docs/rules/jsx-sort-props.md b/docs/rules/jsx-sort-props.md index 106a716864..b1be0d59ed 100644 --- a/docs/rules/jsx-sort-props.md +++ b/docs/rules/jsx-sort-props.md @@ -26,6 +26,7 @@ The following patterns are considered okay and do not cause warnings: ... "jsx-sort-props": [, { "callbacksLast": , + "shorthandFirst": , "ignoreCase": }] ... @@ -49,6 +50,14 @@ When `true`, callbacks must be listed after all other props: ``` +### `shorthandFirst` + +When `true`, short hand props must be listed before all other props, but still respecting the alphabetical order: + +```js + +``` + ## When not to use 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. diff --git a/lib/rules/jsx-sort-props.js b/lib/rules/jsx-sort-props.js index bdbcbe4bab..5e345b36ae 100644 --- a/lib/rules/jsx-sort-props.js +++ b/lib/rules/jsx-sort-props.js @@ -17,6 +17,7 @@ module.exports = function(context) { var configuration = context.options[0] || {}; var ignoreCase = configuration.ignoreCase || false; var callbacksLast = configuration.callbacksLast || false; + var shorthandFirst = configuration.shorthandFirst || false; return { JSXOpeningElement: function(node) { @@ -27,6 +28,8 @@ module.exports = function(context) { var previousPropName = memo.name.name; var currentPropName = decl.name.name; + var previousValue = memo.value; + var currentValue = decl.value; var previousIsCallback = isCallbackPropName(previousPropName); var currentIsCallback = isCallbackPropName(currentPropName); @@ -47,6 +50,16 @@ module.exports = function(context) { } } + if (shorthandFirst) { + if (currentValue && !previousValue) { + return decl; + } + if (!currentValue && previousValue) { + context.report(memo, 'Shorthand props must be listed before all other props'); + return memo; + } + } + if (currentPropName < previousPropName) { context.report(decl, 'Props should be sorted alphabetically'); return memo; @@ -66,6 +79,10 @@ module.exports.schema = [{ callbacksLast: { type: 'boolean' }, + // Whether shorthand properties (without a value) should be listed first + shorthandFirst: { + type: 'boolean' + }, ignoreCase: { type: 'boolean' } diff --git a/tests/lib/rules/jsx-sort-props.js b/tests/lib/rules/jsx-sort-props.js index 89d704a9f8..c7bfb18642 100644 --- a/tests/lib/rules/jsx-sort-props.js +++ b/tests/lib/rules/jsx-sort-props.js @@ -26,9 +26,16 @@ var expectedCallbackError = { message: 'Callbacks must be listed after all other props', type: 'JSXAttribute' }; +var expectedShorthandError = { + message: 'Shorthand props must be listed before all other props', + type: 'JSXAttribute' +}; var callbacksLastArgs = [{ callbacksLast: true }]; +var shorthandFirstArgs = [{ + shorthandFirst: true +}]; var ignoreCaseArgs = [{ ignoreCase: true }]; @@ -52,7 +59,11 @@ ruleTester.run('jsx-sort-props', rule, { {code: ';', options: ignoreCaseArgs, ecmaFeatures: features}, {code: ';', options: ignoreCaseArgs, ecmaFeatures: features}, // Sorting callbacks below all other props - {code: ';', options: callbacksLastArgs, ecmaFeatures: features} + {code: ';', options: callbacksLastArgs, ecmaFeatures: features}, + // Sorting shorthand props before others + {code: ';', options: shorthandFirstArgs, ecmaFeatures: features}, + {code: ';', options: shorthandFirstArgs, ecmaFeatures: features}, + {code: ';', options: shorthandFirstArgs, ecmaFeatures: features} ], invalid: [ {code: ';', errors: [expectedError], ecmaFeatures: features}, @@ -70,6 +81,8 @@ ruleTester.run('jsx-sort-props', rule, { errors: [expectedCallbackError], options: callbacksLastArgs, ecmaFeatures: features - } + }, + {code: ';', errors: [expectedShorthandError], options: shorthandFirstArgs, ecmaFeatures: features}, + {code: ';', errors: [expectedError], options: shorthandFirstArgs, ecmaFeatures: features} ] });