Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
feat: add perfectionist/sort-named-imports and sort-named-exports
https://perfectionist.dev/rules/sort-named-imports
https://perfectionist.dev/rules/sort-named-exports

We had named imports sorted in v1 when tslint was taking care of that. But it got lost during migration to eslint, as I wrongly assumed that import/order will take care of that.
Later on, the support for sorting named imports (but still not exports) was added to the original eslint-plugin-import import-js/eslint-plugin-import#3043
but we have switched to eslint-plugin-import-x since and the porting request of that feature is still pending. un-ts/eslint-plugin-import-x#225

We could consider switching back to eslint-plugin-import but it still has a set of its own, still unresolved issues.
Instead, I decided to try eslint-plugin-perfectionist and the sorting rules from that. Note we are sticking with import/order for sorting and grouping imports for the time being, as more time would be needed to convert the sorting and grouping config to achieve similar behaviour with the perfectionist/sort-imports rule.

There is also perfectionist/sort-exports rule, but it does not provide config options to define grouping and custom sorting, to achieve similar behaviour to import/order with our custom config applied, so for now we won't enforce that rule.
  • Loading branch information
falkenhawk committed Jan 20, 2025
commit af4e68162e15a010ab0ccaed09ed9e9b34ab5c80
28 changes: 26 additions & 2 deletions eslint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import * as tsParser from '@typescript-eslint/parser';
import { Linter } from 'eslint';
import checkFilePlugin from 'eslint-plugin-check-file';
import * as importPlugin from 'eslint-plugin-import'; // aliased to eslint-plugin-import-x https://github.com/un-ts/eslint-plugin-import-x
import perfectionist from 'eslint-plugin-perfectionist';
import globals from 'globals';

type CustomizeOptions = {
Expand Down Expand Up @@ -82,6 +83,21 @@ function customize(options: CustomizeOptions = {}) {
plugins: {
// https://eslint.style/ providing replacement for formatting rules, which are now deprecated in eslint and @typescript-eslint
'@stylistic': { rules: stylistic.rules },
perfectionist,
},
settings: {
// https://perfectionist.dev/guide/getting-started#settings
perfectionist: {
type: 'custom',
ignoreCase: false,
// 'perfectionist' uses .localeCompare() which by default which sorts '123..AaBbCc..'
// we want to put uppercase before lowercase, the rest stays the same (esp. symbols)
// Alphabet from 'perfectionist' could be used, such as
// `Alphabet.generateRecommendedAlphabet().sortByNaturalSort('en-US').placeAllWithCaseBeforeAllWithOtherCase('uppercase').getCharacters()`
// but that contains 128k chars, which is unnecessarily large
// so recreated only the needed part of the alphabet, with uppercase before lowercase
alphabet: '_-.@/#~$0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',
},
},
},
// common settings for typescript files
Expand Down Expand Up @@ -163,7 +179,10 @@ function customize(options: CustomizeOptions = {}) {
// we still sometimes want to use dynamic, sync `require()` instead of `await import()`
'@typescript-eslint/no-require-imports': 'off',
// allow `interface I extends Base<Param> {}` syntax
'@typescript-eslint/no-empty-object-type': ['error', { allowInterfaces: 'with-single-extends' }],
'@typescript-eslint/no-empty-object-type': [
'error',
{ allowInterfaces: 'with-single-extends' },
],
// even though the rules blow are already reconfigured for eslint:recommended,
// they need to be reconfigured again for typescript files, with the same options repeated
'@typescript-eslint/no-unused-expressions': shared['no-unused-expressions'],
Expand Down Expand Up @@ -355,6 +374,11 @@ function customize(options: CustomizeOptions = {}) {
'no-param-reassign': 'error',
'object-shorthand': 'error',
'one-var': ['error', 'never'],
'perfectionist/sort-named-exports': ['error', { groupKind: 'types-first' }],
'perfectionist/sort-named-imports': [
'error',
{ ignoreAlias: true, groupKind: 'types-first' },
],
'prefer-arrow-callback': ['error', { allowNamedFunctions: true }],
...(consoleUsage !== 'allow' && {
'no-console':
Expand Down Expand Up @@ -583,7 +607,7 @@ function customize(options: CustomizeOptions = {}) {
rules: {
'mocha/no-exports': 'off',
},
},
}
);
}

Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@ovos-media/coding-standard",
"version": "3.0.0-rc.0",
"version": "3.0.0-rc.1",
"description": "ovos-media coding standard",
"main": "index.js",
"types": "index.d.ts",
Expand All @@ -26,6 +26,7 @@
"eslint-plugin-import": "npm:eslint-plugin-import-x@^4.6.1",
"eslint-plugin-jest": "^28.10.0",
"eslint-plugin-mocha": "^10.5.0",
"eslint-plugin-perfectionist": "^4.6.0",
"eslint-plugin-react": "^7.37.3",
"eslint-plugin-react-hooks": "^5.1.0",
"globals": "^15.14.0"
Expand Down