diff --git a/lib/rules/jsx-sort-props.js b/lib/rules/jsx-sort-props.js index 10ca976af3..cb09747bb7 100644 --- a/lib/rules/jsx-sort-props.js +++ b/lib/rules/jsx-sort-props.js @@ -40,11 +40,21 @@ function isReservedPropName(name, list) { return list.indexOf(name) >= 0; } -function alphabeticalCompare(a, b, ignoreCase) { - if (ignoreCase) { +function propNameCompare(a, b, options) { + if (options.ignoreCase) { a = a.toLowerCase(); b = b.toLowerCase(); } + if (options.reservedFirst) { + const aIsReserved = isReservedPropName(a, options.reservedList); + const bIsReserved = isReservedPropName(b, options.reservedList); + if ((aIsReserved && bIsReserved) || (!aIsReserved && !bIsReserved)) { + return a.localeCompare(b); + } else if (aIsReserved && !bIsReserved) { + return -1; + } + return 1; + } return a.localeCompare(b); } @@ -77,11 +87,12 @@ function getGroupsOfSortableAttributes(attributes) { return sortableAttributeGroups; } -const generateFixerFunction = (node, context) => { +const generateFixerFunction = (node, context, reservedList) => { const sourceCode = context.getSourceCode(); const attributes = node.attributes.slice(0); const configuration = context.options[0] || {}; const ignoreCase = configuration.ignoreCase || false; + const reservedFirst = configuration.reservedFirst || false; // Sort props according to the context. Only supports ignoreCase. // Since we cannot safely move JSXSpreadAttribute (due to potential variable overrides), @@ -89,7 +100,7 @@ const generateFixerFunction = (node, context) => { const sortableAttributeGroups = getGroupsOfSortableAttributes(attributes); const sortedAttributeGroups = sortableAttributeGroups.slice(0).map(group => group.slice(0).sort((a, b) => - alphabeticalCompare(propName(a), propName(b), ignoreCase) + propNameCompare(propName(a), propName(b), {ignoreCase, reservedFirst, reservedList}) ) ); @@ -235,23 +246,22 @@ module.exports = { const previousIsReserved = isReservedPropName(previousPropName, reservedList); const currentIsReserved = isReservedPropName(currentPropName, reservedList); - if (previousIsReserved && currentIsReserved) { + if ((previousIsReserved && currentIsReserved) || (!previousIsReserved && !currentIsReserved)) { if (!noSortAlphabetically && currentPropName < previousPropName) { context.report({ node: decl, message: 'Props should be sorted alphabetically', - fix: generateFixerFunction(node, context) + fix: generateFixerFunction(node, context, reservedList) }); return memo; } - return decl; } if (!previousIsReserved && currentIsReserved) { context.report({ node: decl, - message: 'Reserved props must be listed before all other props' + message: 'Reserved props must be listed before all other props', + fix: generateFixerFunction(node, context, reservedList) }); - return memo; } return decl; } diff --git a/tests/lib/rules/jsx-sort-props.js b/tests/lib/rules/jsx-sort-props.js index 4cd54ce7b0..9439d4ea64 100644 --- a/tests/lib/rules/jsx-sort-props.js +++ b/tests/lib/rules/jsx-sort-props.js @@ -271,8 +271,21 @@ ruleTester.run('jsx-sort-props', rule, { errors: [expectedError] }, { - code: '', + code: '', options: reservedFirstAsBooleanArgs, + output: '', + errors: [expectedError] + }, + { + code: '', + options: reservedFirstAsBooleanArgs, + output: '', + errors: [expectedError] + }, + { + code: '', + options: reservedFirstAsBooleanArgs, + output: '', errors: [expectedReservedFirstError] }, {