From e28fa0e92832a011a923fc5e3bc5a20705102406 Mon Sep 17 00:00:00 2001 From: Connor Date: Tue, 8 Oct 2024 23:47:44 +0800 Subject: [PATCH] Re-add `importOrderCaseSensitive` option (#184) Implements a custom natural sort algorithm which allows for numeric natural sorting while also sorting all uppercase letters before all lowercase letters, which is the desired behavior here. For example, when `importOrderCaseSensitive` is false (the default): ```js import ExampleComponent from './ExampleComponent'; import ExamplesList from './ExamplesList'; import ExampleWidget from './ExampleWidget'; ``` Compared with `"importOrderCaseSensitive": true`: ```js import ExampleComponent from './ExampleComponent'; import ExampleWidget from './ExampleWidget'; import ExamplesList from './ExamplesList'; ``` Closes #151 --------- Co-authored-by: Ian VanSchooten --- README.md | 29 ++++ src/index.ts | 6 + .../__tests__/natural-sort.spec.ts | 129 +++++++++++++++--- src/natural-sort/index.ts | 39 +++++- src/types.ts | 10 +- .../get-sorted-import-specifiers.spec.ts | 17 +++ .../get-sorted-nodes-by-import-order.spec.ts | 25 ++++ .../merge-nodes-with-matching-flavors.spec.ts | 1 + .../normalize-plugin-options.spec.ts | 13 ++ src/utils/get-sorted-import-specifiers.ts | 15 +- src/utils/get-sorted-nodes-by-import-order.ts | 10 +- src/utils/get-sorted-nodes-group.ts | 14 +- src/utils/normalize-plugin-options.ts | 1 + .../__snapshots__/ppsi.spec.ts.snap | 20 +++ tests/ImportOrderCaseSensitive/mixed-case.ts | 8 ++ tests/ImportOrderCaseSensitive/ppsi.spec.ts | 7 + types/index.d.ts | 24 ++++ 17 files changed, 334 insertions(+), 34 deletions(-) create mode 100644 tests/ImportOrderCaseSensitive/__snapshots__/ppsi.spec.ts.snap create mode 100644 tests/ImportOrderCaseSensitive/mixed-case.ts create mode 100644 tests/ImportOrderCaseSensitive/ppsi.spec.ts diff --git a/README.md b/README.md index 01f834b..4979962 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,7 @@ This project is based on [@trivago/prettier-plugin-sort-imports](https://github. - [7. Enable/disable plugin or use different order in certain folders or files](#7-enabledisable-plugin-or-use-different-order-in-certain-folders-or-files) - [`importOrderTypeScriptVersion`](#importordertypescriptversion) - [`importOrderParserPlugins`](#importorderparserplugins) + - [`importOrderCaseSensitive`](#importordercasesensitive) - [Prevent imports from being sorted](#prevent-imports-from-being-sorted) - [Comments](#comments) - [FAQ / Troubleshooting](#faq--troubleshooting) @@ -139,6 +140,7 @@ module.exports = { importOrder: ['^@core/(.*)$', '', '^@server/(.*)$', '', '^@ui/(.*)$', '', '^[./]'], importOrderParserPlugins: ['typescript', 'jsx', 'decorators-legacy'], importOrderTypeScriptVersion: '5.0.0', + importOrderCaseSensitive: false, }; ``` @@ -393,6 +395,33 @@ with options as a JSON string of the plugin array: "importOrderParserPlugins": [] ``` +#### `importOrderCaseSensitive` + +**type**: `boolean` + +**default value**: `false` + +A boolean value to enable case-sensitivity in the sorting algorithm +used to order imports within each match group. + +For example, when false (or not specified): + +```javascript +import {CatComponent, catFilter, DogComponent, dogFilter} from './animals'; +import ExampleComponent from './ExampleComponent'; +import ExamplesList from './ExamplesList'; +import ExampleWidget from './ExampleWidget'; +``` + +compared with `"importOrderCaseSensitive": true`: + +```javascript +import ExampleComponent from './ExampleComponent'; +import ExampleWidget from './ExampleWidget'; +import ExamplesList from './ExamplesList'; +import {CatComponent, DogComponent, catFilter, dogFilter} from './animals'; +``` + ### Prevent imports from being sorted This plugin supports standard prettier ignore comments. By default, side-effect imports (like diff --git a/src/index.ts b/src/index.ts index dbd5cff..63625ef 100644 --- a/src/index.ts +++ b/src/index.ts @@ -50,6 +50,12 @@ export const options: Record< description: 'Version of TypeScript in use in the project. Determines some output syntax when using TypeScript.', }, + importOrderCaseSensitive: { + type: 'boolean', + category: 'Global', + default: false, + description: 'Provide a case sensitivity boolean flag', + }, }; export const parsers = { diff --git a/src/natural-sort/__tests__/natural-sort.spec.ts b/src/natural-sort/__tests__/natural-sort.spec.ts index fa57e55..eabee67 100644 --- a/src/natural-sort/__tests__/natural-sort.spec.ts +++ b/src/natural-sort/__tests__/natural-sort.spec.ts @@ -1,26 +1,115 @@ -import { expect, test } from 'vitest'; +import { describe, expect, test } from 'vitest'; -import { naturalSort } from '..'; +import { naturalSort, naturalSortCaseSensitive } from '..'; -test('should sort normal things alphabetically', () => { - expect( - ['a', 'h', 'b', 'i', 'c', 'd', 'j', 'e', 'k', 'f', 'g'].sort((a, b) => - naturalSort(a, b), - ), - ).toEqual(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k']); -}); +describe('naturalSort', () => { + test('should sort normal things alphabetically', () => { + expect( + ['a', 'h', 'b', 'i', 'c', 'd', 'j', 'e', 'k', 'f', 'g'].sort( + (a, b) => naturalSort(a, b), + ), + ).toEqual(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k']); + }); + + test('should ignore capitalization differences', () => { + expect( + ['./ExampleComponent', './ExamplesList', './ExampleWidget'].sort( + (a, b) => naturalSort(a, b), + ), + ).toEqual(['./ExampleComponent', './ExamplesList', './ExampleWidget']); + }); -test('should ignore capitalization differences', () => { - // We have no option to cause case-sensitive sorting, so this is the "default" case! - expect( - ['./ExampleView', './ExamplesList'].sort((a, b) => naturalSort(a, b)), - ).toEqual(['./ExamplesList', './ExampleView']); + test('should sort things numerically', () => { + expect( + [ + 'a2', + 'a3', + 'a10', + 'a1', + 'a11', + 'a9', + 'a1b', + 'file000b', + 'file000a', + 'file00a', + 'file00z', + ].sort(naturalSort), + ).toEqual([ + 'a1', + 'a1b', + 'a2', + 'a3', + 'a9', + 'a10', + 'a11', + 'file000a', + 'file00a', + 'file000b', + 'file00z', + ]); + }); }); -test('should sort things numerically', () => { - expect( - ['a2', 'a3', 'a10', 'a1', 'a11', 'a9'].sort((a, b) => - naturalSort(a, b), - ), - ).toEqual(['a1', 'a2', 'a3', 'a9', 'a10', 'a11']); +describe('naturalSortCaseSensitive', () => { + test('should not ignore capitalization differences', () => { + expect( + ['./ExampleComponent', './ExamplesList', './ExampleWidget'].sort( + (a, b) => naturalSortCaseSensitive(a, b), + ), + ).toEqual(['./ExampleComponent', './ExampleWidget', './ExamplesList']); + }); + + test('should sort numerically and case-sensitively', () => { + expect( + [ + 'file1', + 'File10', + 'AbA', + 'file10', + 'files10', + 'file1z', + 'file10ab', + 'file2s', + 'a', + 'Ab', + 'file20', + 'file22', + 'file11', + 'file2', + 'File20', + 'file000b', + 'file000a', + 'file00a', + 'file00z', + 'aaa', + 'AAA', + 'bBb', + 'BBB', + ].sort(naturalSortCaseSensitive), + ).toEqual([ + 'AAA', + 'Ab', + 'AbA', + 'BBB', + 'File10', + 'File20', + 'a', + 'aaa', + 'bBb', + 'file000a', + 'file00a', + 'file000b', + 'file00z', + 'file1', + 'file1z', + 'file2', + 'file2s', + 'file10', + 'file10ab', + 'file11', + 'file20', + 'file22', + 'files10', + ]); + }); }); diff --git a/src/natural-sort/index.ts b/src/natural-sort/index.ts index afe301b..2117603 100644 --- a/src/natural-sort/index.ts +++ b/src/natural-sort/index.ts @@ -1,12 +1,47 @@ export function naturalSort(a: string, b: string): number { const left = typeof a === 'string' ? a : String(a); - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Collator/Collator#syntax const sortOptions: Intl.CollatorOptions = { sensitivity: 'base', numeric: true, caseFirst: 'lower', }; - return left.localeCompare(b, 'en', sortOptions); } + +/** + * Using a custom comparison function here, as `String.localeCompare` does not + * support sorting characters with all uppercase letters before lowercase + * letters, which is the desired behavior for a case-sensitive import sort. When + * `sensitivity` is set to `base`, `String.localeCompare` sorts alphabetically + * and then by case, but we want to sort by case first (then alphabetical). + */ +const numericRegex = /^\d+/; +export function naturalSortCaseSensitive(a: string, b: string) { + let aIndex = 0; + let bIndex = 0; + while (aIndex < Math.max(a.length, b.length)) { + // check if we've encountered a number and compare appropriately if so + const aNumericMatch = a.slice(aIndex).match(numericRegex); + const bNumericMatch = b.slice(bIndex).match(numericRegex); + if (aNumericMatch && !bNumericMatch) return -1; + if (!aNumericMatch && bNumericMatch) return 1; + if (aNumericMatch && bNumericMatch) { + const aNumber = parseInt(aNumericMatch[0]); + const bNumber = parseInt(bNumericMatch[0]); + if (aNumber > bNumber) return 1; + if (aNumber < bNumber) return -1; + aIndex += aNumericMatch[0].length; + bIndex += bNumericMatch[0].length; + } + // otherwise just compare characters directly + const aChar = a[aIndex]; + const bChar = b[bIndex]; + if (aChar && !bChar) return 1; + if (!aChar && bChar) return -1; + if (aChar !== bChar) return aChar.charCodeAt(0) - bChar.charCodeAt(0); + aIndex++; + bIndex++; + } + return 0; +} diff --git a/src/types.ts b/src/types.ts index e8974fb..136d93c 100644 --- a/src/types.ts +++ b/src/types.ts @@ -26,7 +26,10 @@ export interface PrettierOptions /** Subset of options that need to be normalized, or affect normalization */ export type NormalizableOptions = Pick< PrettierOptions, - 'importOrder' | 'importOrderParserPlugins' | 'importOrderTypeScriptVersion' + | 'importOrder' + | 'importOrderParserPlugins' + | 'importOrderTypeScriptVersion' + | 'importOrderCaseSensitive' > & // filepath can be undefined when running prettier via the api on text input Pick, 'filepath'>; @@ -63,6 +66,7 @@ export type ImportRelated = ImportOrLine | SomeSpecifier; export interface ExtendedOptions { importOrder: PrettierOptions['importOrder']; importOrderCombineTypeAndValueImports: boolean; + importOrderCaseSensitive: boolean; hasAnyCustomGroupSeparatorsInImportOrder: boolean; provideGapAfterTopOfFileComments: boolean; plugins: ParserPlugin[]; @@ -79,7 +83,9 @@ export type GetSortedNodes = ( export type GetSortedNodesByImportOrder = ( nodes: ImportDeclaration[], - options: Pick, + options: Pick & { + importOrderCaseSensitive?: boolean; + }, ) => ImportOrLine[]; export type GetChunkTypeOfNode = (node: ImportDeclaration) => ChunkType; diff --git a/src/utils/__tests__/get-sorted-import-specifiers.spec.ts b/src/utils/__tests__/get-sorted-import-specifiers.spec.ts index b40dab5..fa015be 100644 --- a/src/utils/__tests__/get-sorted-import-specifiers.spec.ts +++ b/src/utils/__tests__/get-sorted-import-specifiers.spec.ts @@ -70,3 +70,20 @@ test('should group type imports after value imports - flow', () => { 'TypeB', ]); }); + +test('should sort case-sensitively', () => { + const code = `import { ExampleComponent, ExamplesList, ExampleWidget } from '@components/e';`; + const [importNode] = getImportNodes(code); + const sortedImportSpecifiers = getSortedImportSpecifiers(importNode, { + importOrderCaseSensitive: true, + }); + const specifiersList = getSortedNodesModulesNames( + sortedImportSpecifiers.specifiers, + ); + + expect(specifiersList).toEqual([ + 'ExampleComponent', + 'ExampleWidget', + 'ExamplesList', + ]); +}); diff --git a/src/utils/__tests__/get-sorted-nodes-by-import-order.spec.ts b/src/utils/__tests__/get-sorted-nodes-by-import-order.spec.ts index 5d18a5f..eb0c4be 100644 --- a/src/utils/__tests__/get-sorted-nodes-by-import-order.spec.ts +++ b/src/utils/__tests__/get-sorted-nodes-by-import-order.spec.ts @@ -274,3 +274,28 @@ test('it does not add multiple custom import separators', () => { './local', ]); }); + +test('it should sort nodes case-sensitively', () => { + const result = getImportNodes(code); + const sorted = getSortedNodesByImportOrder(result, { + importOrder: testingOnly.normalizeImportOrderOption(['^[./]']), + importOrderCaseSensitive: true, + }) as ImportDeclaration[]; + expect(getSortedNodesNamesAndNewlines(sorted)).toEqual([ + 'node:fs/promises', + 'node:url', + 'path', + 'BY', + 'Ba', + 'XY', + 'Xa', + 'a', + 'c', + 'g', + 'k', + 't', + 'x', + 'z', + './local', + ]); +}); diff --git a/src/utils/__tests__/merge-nodes-with-matching-flavors.spec.ts b/src/utils/__tests__/merge-nodes-with-matching-flavors.spec.ts index 2a2aae6..3bc6258 100644 --- a/src/utils/__tests__/merge-nodes-with-matching-flavors.spec.ts +++ b/src/utils/__tests__/merge-nodes-with-matching-flavors.spec.ts @@ -13,6 +13,7 @@ const defaultOptions = examineAndNormalizePluginOptions({ // First separator for top-of-file comments, second to separate side-effect and ignored chunks, for easier test readability importOrder: testingOnly.normalizeImportOrderOption(['', '']), importOrderTypeScriptVersion: '5.0.0', + importOrderCaseSensitive: false, importOrderParserPlugins: [], filepath: __filename, }); diff --git a/src/utils/__tests__/normalize-plugin-options.spec.ts b/src/utils/__tests__/normalize-plugin-options.spec.ts index ecdd1df..92133c7 100644 --- a/src/utils/__tests__/normalize-plugin-options.spec.ts +++ b/src/utils/__tests__/normalize-plugin-options.spec.ts @@ -96,6 +96,7 @@ describe('examineAndNormalizePluginOptions', () => { examineAndNormalizePluginOptions({ importOrder: DEFAULT_IMPORT_ORDER, importOrderParserPlugins: [], + importOrderCaseSensitive: false, importOrderTypeScriptVersion: '1.0.0', filepath: __filename, } as NormalizableOptions), @@ -107,6 +108,7 @@ describe('examineAndNormalizePluginOptions', () => { '^[.]', ], importOrderCombineTypeAndValueImports: true, + importOrderCaseSensitive: false, plugins: [], provideGapAfterTopOfFileComments: false, }); @@ -121,6 +123,7 @@ describe('examineAndNormalizePluginOptions', () => { '^[./]', ], importOrderParserPlugins: [], + importOrderCaseSensitive: false, importOrderTypeScriptVersion: '1.0.0', filepath: __filename, } as NormalizableOptions), @@ -133,6 +136,7 @@ describe('examineAndNormalizePluginOptions', () => { '^[./]', ], importOrderCombineTypeAndValueImports: true, + importOrderCaseSensitive: false, plugins: [], provideGapAfterTopOfFileComments: false, }); @@ -142,6 +146,7 @@ describe('examineAndNormalizePluginOptions', () => { examineAndNormalizePluginOptions({ importOrder: [''], importOrderParserPlugins: [], + importOrderCaseSensitive: false, importOrderTypeScriptVersion: '1.0.0', filepath: __filename, } as NormalizableOptions), @@ -153,6 +158,7 @@ describe('examineAndNormalizePluginOptions', () => { THIRD_PARTY_MODULES_SPECIAL_WORD, ], importOrderCombineTypeAndValueImports: true, + importOrderCaseSensitive: false, plugins: [], provideGapAfterTopOfFileComments: true, }); @@ -173,6 +179,7 @@ describe('examineAndNormalizePluginOptions', () => { '^[.]', ], importOrderCombineTypeAndValueImports: true, + importOrderCaseSensitive: false, plugins: ['typescript'], provideGapAfterTopOfFileComments: false, }); @@ -184,6 +191,7 @@ describe('examineAndNormalizePluginOptions', () => { importOrder: DEFAULT_IMPORT_ORDER, importOrderParserPlugins: ['typescript', 'jsx'], importOrderTypeScriptVersion: '5.0.0', + importOrderCaseSensitive: false, filepath: __filename, } as NormalizableOptions), ).toEqual({ @@ -194,6 +202,7 @@ describe('examineAndNormalizePluginOptions', () => { '^[.]', ], importOrderCombineTypeAndValueImports: true, + importOrderCaseSensitive: false, plugins: ['typescript'], provideGapAfterTopOfFileComments: false, }); @@ -203,6 +212,7 @@ describe('examineAndNormalizePluginOptions', () => { examineAndNormalizePluginOptions({ importOrder: DEFAULT_IMPORT_ORDER, importOrderParserPlugins: [], + importOrderCaseSensitive: false, importOrderTypeScriptVersion: '1.0.0', filepath: undefined, } as NormalizableOptions), @@ -214,6 +224,7 @@ describe('examineAndNormalizePluginOptions', () => { '^[.]', ], importOrderCombineTypeAndValueImports: true, + importOrderCaseSensitive: false, plugins: [], provideGapAfterTopOfFileComments: false, }); @@ -224,6 +235,7 @@ describe('examineAndNormalizePluginOptions', () => { examineAndNormalizePluginOptions({ importOrder: [], importOrderParserPlugins: [], + importOrderCaseSensitive: false, importOrderTypeScriptVersion: '1.0.0', filepath: __filename, } as NormalizableOptions), @@ -231,6 +243,7 @@ describe('examineAndNormalizePluginOptions', () => { hasAnyCustomGroupSeparatorsInImportOrder: false, importOrder: [], importOrderCombineTypeAndValueImports: true, + importOrderCaseSensitive: false, plugins: [], provideGapAfterTopOfFileComments: false, }); diff --git a/src/utils/get-sorted-import-specifiers.ts b/src/utils/get-sorted-import-specifiers.ts index 19cc050..87013e6 100644 --- a/src/utils/get-sorted-import-specifiers.ts +++ b/src/utils/get-sorted-import-specifiers.ts @@ -1,6 +1,7 @@ import { type ImportDeclaration } from '@babel/types'; -import { naturalSort } from '../natural-sort'; +import type { PluginConfig } from '../../types'; +import { naturalSort, naturalSortCaseSensitive } from '../natural-sort'; /** * This function returns import nodes with alphabetically sorted module @@ -12,7 +13,11 @@ import { naturalSort } from '../natural-sort'; * * @param node Import declaration node */ -export const getSortedImportSpecifiers = (node: ImportDeclaration) => { +export const getSortedImportSpecifiers = ( + node: ImportDeclaration, + options?: Pick, +) => { + const { importOrderCaseSensitive } = options || {}; node.specifiers.sort((a, b) => { if (a.type !== b.type) { return a.type === 'ImportDefaultSpecifier' ? -1 : 1; @@ -25,8 +30,10 @@ export const getSortedImportSpecifiers = (node: ImportDeclaration) => { // flow uses null for value import specifiers return a.importKind === 'value' || a.importKind == null ? -1 : 1; } - - return naturalSort(a.local.name, b.local.name); + const sortFn = importOrderCaseSensitive + ? naturalSortCaseSensitive + : naturalSort; + return sortFn(a.local.name, b.local.name); }); return node; }; diff --git a/src/utils/get-sorted-nodes-by-import-order.ts b/src/utils/get-sorted-nodes-by-import-order.ts index 791ad6e..dc0f8e3 100644 --- a/src/utils/get-sorted-nodes-by-import-order.ts +++ b/src/utils/get-sorted-nodes-by-import-order.ts @@ -21,7 +21,7 @@ import { */ export const getSortedNodesByImportOrder: GetSortedNodesByImportOrder = ( originalNodes, - { importOrder }, + { importOrder, importOrderCaseSensitive }, ) => { if ( process.env.NODE_ENV === 'test' && @@ -83,10 +83,14 @@ export const getSortedNodesByImportOrder: GetSortedNodesByImportOrder = ( if (groupNodes.length === 0) continue; - const sortedInsideGroup = getSortedNodesGroup(groupNodes); + const sortedInsideGroup = getSortedNodesGroup(groupNodes, { + importOrderCaseSensitive, + }); // Sort the import specifiers - sortedInsideGroup.forEach((node) => getSortedImportSpecifiers(node)); + sortedInsideGroup.forEach((node) => + getSortedImportSpecifiers(node, { importOrderCaseSensitive }), + ); finalNodes.push(...sortedInsideGroup); } diff --git a/src/utils/get-sorted-nodes-group.ts b/src/utils/get-sorted-nodes-group.ts index da58f36..9e6d2ae 100644 --- a/src/utils/get-sorted-nodes-group.ts +++ b/src/utils/get-sorted-nodes-group.ts @@ -1,7 +1,15 @@ import type { ImportDeclaration } from '@babel/types'; -import { naturalSort } from '../natural-sort'; +import type { PluginConfig } from '../../types'; +import { naturalSort, naturalSortCaseSensitive } from '../natural-sort'; -export const getSortedNodesGroup = (imports: ImportDeclaration[]) => { - return imports.sort((a, b) => naturalSort(a.source.value, b.source.value)); +export const getSortedNodesGroup = ( + imports: ImportDeclaration[], + options?: Pick, +) => { + const { importOrderCaseSensitive } = options || {}; + const sortFn = importOrderCaseSensitive + ? naturalSortCaseSensitive + : naturalSort; + return imports.sort((a, b) => sortFn(a.source.value, b.source.value)); }; diff --git a/src/utils/normalize-plugin-options.ts b/src/utils/normalize-plugin-options.ts index c114424..aa692c3 100644 --- a/src/utils/normalize-plugin-options.ts +++ b/src/utils/normalize-plugin-options.ts @@ -107,6 +107,7 @@ export function examineAndNormalizePluginOptions( return { importOrder, importOrderCombineTypeAndValueImports, + importOrderCaseSensitive: !!options.importOrderCaseSensitive, hasAnyCustomGroupSeparatorsInImportOrder: importOrder.some( isCustomGroupSeparator, ), diff --git a/tests/ImportOrderCaseSensitive/__snapshots__/ppsi.spec.ts.snap b/tests/ImportOrderCaseSensitive/__snapshots__/ppsi.spec.ts.snap new file mode 100644 index 0000000..a93b151 --- /dev/null +++ b/tests/ImportOrderCaseSensitive/__snapshots__/ppsi.spec.ts.snap @@ -0,0 +1,20 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`mixed-case.ts - typescript-verify > mixed-case.ts 1`] = ` + +import c from "c"; +import b from "b"; +import a from "a"; + +import {cat, Dog} from "C"; +import B from "B"; +import A from "A"; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +import A from "A"; +import B from "B"; +import { Dog, cat } from "C"; +import a from "a"; +import b from "b"; +import c from "c"; + +`; diff --git a/tests/ImportOrderCaseSensitive/mixed-case.ts b/tests/ImportOrderCaseSensitive/mixed-case.ts new file mode 100644 index 0000000..7b0a094 --- /dev/null +++ b/tests/ImportOrderCaseSensitive/mixed-case.ts @@ -0,0 +1,8 @@ + +import c from "c"; +import b from "b"; +import a from "a"; + +import {cat, Dog} from "C"; +import B from "B"; +import A from "A"; diff --git a/tests/ImportOrderCaseSensitive/ppsi.spec.ts b/tests/ImportOrderCaseSensitive/ppsi.spec.ts new file mode 100644 index 0000000..596a005 --- /dev/null +++ b/tests/ImportOrderCaseSensitive/ppsi.spec.ts @@ -0,0 +1,7 @@ +import {run_spec} from '../../test-setup/run_spec'; + +run_spec(__dirname, ["typescript"], { + importOrder: ['^@core/(.*)$', '^@server/(.*)', '^@ui/(.*)$', '^[./]'], + importOrderCaseSensitive: true, + importOrderParserPlugins: ['typescript'] +}); diff --git a/types/index.d.ts b/types/index.d.ts index 35886bb..3578c73 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -45,6 +45,30 @@ export interface PluginConfig { */ importOrderTypeScriptVersion?: string; + /** + * A boolean value to enable case-sensitivity in the sorting algorithm + * used to order imports within each match group. + * + * For example, when false (or not specified): + * + * ```js + * import ExampleComponent from './ExampleComponent'; + * import ExamplesList from './ExamplesList'; + * import ExampleWidget from './ExampleWidget'; + * ``` + * + * compared with `"importOrderCaseSensitive": true`: + * + * ```js + * import ExampleComponent from './ExampleComponent'; + * import ExampleWidget from './ExampleWidget'; + * import ExamplesList from './ExamplesList'; + * ``` + * + * @default false + */ + importOrderCaseSensitive?: boolean; + /** * A collection of plugins for babel parser. The plugin passes this list to babel parser, so it can understand the syntaxes * used in the file being formatted. The plugin uses prettier itself to figure out the parser it needs to use but if that fails,