From c28fa7cc8af6c2277fa697212e9de7362bb1cd60 Mon Sep 17 00:00:00 2001 From: dbrewer5 Date: Thu, 26 Dec 2019 17:05:14 -0800 Subject: [PATCH] [New] `order`: added `caseInsensitive` as an additional option to `alphabetize` - imp: mutateRanksToAlphabetizeV2 added to handle case insensitive sorting - tests: add two test cases for alphabetize.caseInsensitive: true - docs: added documentation for new options: alphabetize.caseInsensitive - imp: merged mutateRanksToAlphabetizeV2 to original - changelog: updated with caseInsensitive addition --- CHANGELOG.md | 5 +++++ docs/rules/order.md | 6 +++++- src/rules/order.js | 16 +++++++++----- tests/src/rules/order.js | 46 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 67 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b64f1d824..cbd12b251 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ This project adheres to [Semantic Versioning](http://semver.org/). This change log adheres to standards from [Keep a CHANGELOG](http://keepachangelog.com). ## [Unreleased] +### Added +- [`order`]: added `caseInsensitive` as an additional option to `alphabetize` ([#1586], thanks [@dbrewer5]) + ### Fixed - [`no-unused-modules`]: fix usage of `import/extensions` settings ([#1560], thanks [@stekycz]) @@ -625,6 +628,7 @@ for info on changes for earlier releases. [`memo-parser`]: ./memo-parser/README.md +[#1586]: https://github.com/benmosher/eslint-plugin-import/pull/1586 [#1563]: https://github.com/benmosher/eslint-plugin-import/pull/1563 [#1560]: https://github.com/benmosher/eslint-plugin-import/pull/1560 [#1551]: https://github.com/benmosher/eslint-plugin-import/pull/1551 @@ -1046,3 +1050,4 @@ for info on changes for earlier releases. [@randallreedjr]: https://github.com/randallreedjr [@Pessimistress]: https://github.com/Pessimistress [@stekycz]: https://github.com/stekycz +[@dbrewer5]: https://github.com/dbrewer5 diff --git a/docs/rules/order.md b/docs/rules/order.md index b5c4902ac..8012e637f 100644 --- a/docs/rules/order.md +++ b/docs/rules/order.md @@ -189,16 +189,18 @@ import index from './'; import sibling from './foo'; ``` -### `alphabetize: {order: asc|desc|ignore}`: +### `alphabetize: {order: asc|desc|ignore, caseInsensitive: true|false}`: Sort the order within each group in alphabetical manner based on **import path**: - `order`: use `asc` to sort in ascending order, and `desc` to sort in descending order (default: `ignore`). +- `caseInsensitive`: use `true` to ignore case, and `false` to consider case (default: `false`). Example setting: ```js alphabetize: { order: 'asc', /* sort in ascending order. Options: ['ignore', 'asc', 'desc'] */ + caseInsensitive: true /* ignore case. Options: [true, false] */ } ``` @@ -210,12 +212,14 @@ import React, { PureComponent } from 'react'; import aTypes from 'prop-types'; import { compose, apply } from 'xcompose'; import * as classnames from 'classnames'; +import blist from 'BList'; ``` While this will pass: ```js /* eslint import/order: ["error", {"alphabetize": true}] */ +import blist from 'BList'; import * as classnames from 'classnames'; import aTypes from 'prop-types'; import React, { PureComponent } from 'react'; diff --git a/src/rules/order.js b/src/rules/order.js index 7a7629bf7..a842f60af 100644 --- a/src/rules/order.js +++ b/src/rules/order.js @@ -267,7 +267,7 @@ function importsSorterDesc(importA, importB) { return 0 } -function mutateRanksToAlphabetize(imported, order) { +function mutateRanksToAlphabetize(imported, alphabetizeOptions) { const groupedByRanks = imported.reduce(function(acc, importedItem) { if (!Array.isArray(acc[importedItem.rank])) { acc[importedItem.rank] = [] @@ -278,10 +278,11 @@ function mutateRanksToAlphabetize(imported, order) { const groupRanks = Object.keys(groupedByRanks) - const sorterFn = order === 'asc' ? importsSorterAsc : importsSorterDesc + const sorterFn = alphabetizeOptions.order === 'asc' ? importsSorterAsc : importsSorterDesc + const comparator = alphabetizeOptions.caseInsensitive ? (a, b) => sorterFn(String(a).toLowerCase(), String(b).toLowerCase()) : (a, b) => sorterFn(a, b) // sort imports locally within their group groupRanks.forEach(function(groupRank) { - groupedByRanks[groupRank].sort(sorterFn) + groupedByRanks[groupRank].sort(comparator) }) // assign globally unique rank to each import @@ -487,8 +488,9 @@ function makeNewlinesBetweenReport (context, imported, newlinesBetweenImports) { function getAlphabetizeConfig(options) { const alphabetize = options.alphabetize || {} const order = alphabetize.order || 'ignore' + const caseInsensitive = alphabetize.caseInsensitive || false - return {order} + return {order, caseInsensitive} } module.exports = { @@ -540,6 +542,10 @@ module.exports = { alphabetize: { type: 'object', properties: { + caseInsensitive: { + type: 'boolean', + default: false, + }, order: { enum: ['ignore', 'asc', 'desc'], default: 'ignore', @@ -604,7 +610,7 @@ module.exports = { } if (alphabetize.order !== 'ignore') { - mutateRanksToAlphabetize(imported, alphabetize.order) + mutateRanksToAlphabetize(imported, alphabetize) } makeOutOfOrderReport(context, imported) diff --git a/tests/src/rules/order.js b/tests/src/rules/order.js index 153a92338..11309f933 100644 --- a/tests/src/rules/order.js +++ b/tests/src/rules/order.js @@ -1870,5 +1870,51 @@ ruleTester.run('order', rule, { message: '`bar` import should occur before import of `Bar`', }], }), + // Option alphabetize {order: 'asc': caseInsensitive: true} + test({ + code: ` + import b from 'foo'; + import a from 'Bar'; + + import index from './'; + `, + output: ` + import a from 'Bar'; + import b from 'foo'; + + import index from './'; + `, + options: [{ + groups: ['external', 'index'], + alphabetize: {order: 'asc', caseInsensitive: true}, + }], + errors: [{ + ruleID: 'order', + message: '`Bar` import should occur before import of `foo`', + }], + }), + // Option alphabetize {order: 'desc': caseInsensitive: true} + test({ + code: ` + import a from 'Bar'; + import b from 'foo'; + + import index from './'; + `, + output: ` + import b from 'foo'; + import a from 'Bar'; + + import index from './'; + `, + options: [{ + groups: ['external', 'index'], + alphabetize: {order: 'desc', caseInsensitive: true}, + }], + errors: [{ + ruleID: 'order', + message: '`foo` import should occur before import of `Bar`', + }], + }), ].filter((t) => !!t), })