eslint-plugin-perfectionist 4.2.0 → 4.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/alphabet.d.ts +176 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +8 -0
- package/dist/rules/sort-array-includes.js +2 -0
- package/dist/rules/sort-classes.js +6 -2
- package/dist/rules/sort-decorators.js +4 -0
- package/dist/rules/sort-enums.js +5 -0
- package/dist/rules/sort-exports.js +4 -0
- package/dist/rules/sort-heritage-clauses.js +4 -0
- package/dist/rules/sort-imports.js +5 -0
- package/dist/rules/sort-interfaces.js +1 -0
- package/dist/rules/sort-intersection-types.js +4 -0
- package/dist/rules/sort-jsx-props.js +4 -0
- package/dist/rules/sort-maps.js +4 -0
- package/dist/rules/sort-modules.js +6 -2
- package/dist/rules/sort-named-exports.js +4 -0
- package/dist/rules/sort-named-imports.js +4 -0
- package/dist/rules/sort-object-types.js +10 -11
- package/dist/rules/sort-objects.js +32 -5
- package/dist/rules/sort-switch-case.js +4 -0
- package/dist/rules/sort-union-types.js +4 -0
- package/dist/rules/sort-variable-declarations.js +4 -0
- package/dist/utils/alphabet.js +385 -0
- package/dist/utils/common-json-schemas.js +16 -1
- package/dist/utils/compare.js +88 -38
- package/dist/utils/convert-boolean-to-sign.js +4 -0
- package/dist/{rules → utils}/get-custom-groups-compare-options.js +1 -0
- package/dist/utils/get-matching-context-options.js +18 -0
- package/dist/utils/get-settings.js +1 -0
- package/dist/utils/is-node-function-type.js +15 -0
- package/dist/utils/validate-custom-sort-configuration.js +11 -0
- package/dist/{rules → utils}/validate-generated-groups-configuration.js +1 -1
- package/package.json +7 -3
- package/readme.md +4 -3
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' })
|
|
3
3
|
let typeJsonSchema = {
|
|
4
|
-
enum: ['alphabetical', 'natural', 'line-length'],
|
|
4
|
+
enum: ['alphabetical', 'natural', 'line-length', 'custom'],
|
|
5
5
|
description: 'Specifies the sorting method.',
|
|
6
6
|
type: 'string',
|
|
7
7
|
}
|
|
@@ -11,6 +11,10 @@ let orderJsonSchema = {
|
|
|
11
11
|
enum: ['asc', 'desc'],
|
|
12
12
|
type: 'string',
|
|
13
13
|
}
|
|
14
|
+
let alphabetJsonSchema = {
|
|
15
|
+
description: 'Alphabet to use for the `custom` sort type.',
|
|
16
|
+
type: 'string',
|
|
17
|
+
}
|
|
14
18
|
let localesJsonSchema = {
|
|
15
19
|
oneOf: [
|
|
16
20
|
{
|
|
@@ -96,6 +100,15 @@ let newlinesBetweenJsonSchema = {
|
|
|
96
100
|
enum: ['ignore', 'always', 'never'],
|
|
97
101
|
type: 'string',
|
|
98
102
|
}
|
|
103
|
+
let useConfigurationIfJsonSchema = {
|
|
104
|
+
properties: {
|
|
105
|
+
allNamesMatchPattern: {
|
|
106
|
+
type: 'string',
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
additionalProperties: false,
|
|
110
|
+
type: 'object',
|
|
111
|
+
}
|
|
99
112
|
let customGroupSortJsonSchema = {
|
|
100
113
|
type: {
|
|
101
114
|
enum: ['alphabetical', 'line-length', 'natural', 'unsorted'],
|
|
@@ -169,6 +182,7 @@ let elementNamePatternJsonSchema = {
|
|
|
169
182
|
description: 'Element name pattern filter.',
|
|
170
183
|
type: 'string',
|
|
171
184
|
}
|
|
185
|
+
exports.alphabetJsonSchema = alphabetJsonSchema
|
|
172
186
|
exports.buildCustomGroupModifiersJsonSchema =
|
|
173
187
|
buildCustomGroupModifiersJsonSchema
|
|
174
188
|
exports.buildCustomGroupSelectorJsonSchema = buildCustomGroupSelectorJsonSchema
|
|
@@ -184,3 +198,4 @@ exports.partitionByCommentJsonSchema = partitionByCommentJsonSchema
|
|
|
184
198
|
exports.partitionByNewLineJsonSchema = partitionByNewLineJsonSchema
|
|
185
199
|
exports.specialCharactersJsonSchema = specialCharactersJsonSchema
|
|
186
200
|
exports.typeJsonSchema = typeJsonSchema
|
|
201
|
+
exports.useConfigurationIfJsonSchema = useConfigurationIfJsonSchema
|
package/dist/utils/compare.js
CHANGED
|
@@ -1,53 +1,103 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' })
|
|
3
3
|
const naturalOrderby = require('natural-orderby')
|
|
4
|
+
const convertBooleanToSign = require('./convert-boolean-to-sign.js')
|
|
5
|
+
let alphabetCache = /* @__PURE__ */ new Map()
|
|
4
6
|
let compare = (a, b, options) => {
|
|
5
|
-
let orderCoefficient = options.order === 'asc' ? 1 : -1
|
|
6
7
|
let sortingFunction
|
|
7
8
|
let nodeValueGetter = options.nodeValueGetter ?? (node => node.name)
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
options
|
|
11
|
-
|
|
9
|
+
switch (options.type) {
|
|
10
|
+
case 'alphabetical':
|
|
11
|
+
sortingFunction = getAlphabeticalSortingFunction(options, nodeValueGetter)
|
|
12
|
+
break
|
|
13
|
+
case 'natural':
|
|
14
|
+
sortingFunction = getNaturalSortingFunction(options, nodeValueGetter)
|
|
15
|
+
break
|
|
16
|
+
case 'custom':
|
|
17
|
+
sortingFunction = getCustomSortingFunction(options, nodeValueGetter)
|
|
18
|
+
break
|
|
19
|
+
case 'line-length':
|
|
20
|
+
sortingFunction = getLineLengthSortingFunction(options, nodeValueGetter)
|
|
21
|
+
}
|
|
22
|
+
return (
|
|
23
|
+
convertBooleanToSign.convertBooleanToSign(options.order === 'asc') *
|
|
24
|
+
sortingFunction(a, b)
|
|
25
|
+
)
|
|
26
|
+
}
|
|
27
|
+
let getAlphabeticalSortingFunction = (
|
|
28
|
+
{ specialCharacters, ignoreCase, locales },
|
|
29
|
+
nodeValueGetter,
|
|
30
|
+
) => {
|
|
31
|
+
let formatString = getFormatStringFunction(ignoreCase, specialCharacters)
|
|
32
|
+
return (aNode, bNode) =>
|
|
33
|
+
formatString(nodeValueGetter(aNode)).localeCompare(
|
|
34
|
+
formatString(nodeValueGetter(bNode)),
|
|
35
|
+
locales,
|
|
12
36
|
)
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
37
|
+
}
|
|
38
|
+
let getNaturalSortingFunction = (
|
|
39
|
+
{ specialCharacters, ignoreCase, locales },
|
|
40
|
+
nodeValueGetter,
|
|
41
|
+
) => {
|
|
42
|
+
let naturalCompare = naturalOrderby.compare({
|
|
43
|
+
locale: locales.toString(),
|
|
44
|
+
})
|
|
45
|
+
let formatString = getFormatStringFunction(ignoreCase, specialCharacters)
|
|
46
|
+
return (aNode, bNode) =>
|
|
47
|
+
naturalCompare(
|
|
48
|
+
formatString(nodeValueGetter(aNode)),
|
|
49
|
+
formatString(nodeValueGetter(bNode)),
|
|
25
50
|
)
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
51
|
+
}
|
|
52
|
+
let getCustomSortingFunction = (
|
|
53
|
+
{ specialCharacters, ignoreCase, alphabet },
|
|
54
|
+
nodeValueGetter,
|
|
55
|
+
) => {
|
|
56
|
+
let formatString = getFormatStringFunction(ignoreCase, specialCharacters)
|
|
57
|
+
let indexByCharacters = alphabetCache.get(alphabet)
|
|
58
|
+
if (!indexByCharacters) {
|
|
59
|
+
indexByCharacters = /* @__PURE__ */ new Map()
|
|
60
|
+
for (let [index, character] of [...alphabet].entries()) {
|
|
61
|
+
indexByCharacters.set(character, index)
|
|
62
|
+
}
|
|
63
|
+
alphabetCache.set(alphabet, indexByCharacters)
|
|
64
|
+
}
|
|
65
|
+
return (aNode, bNode) => {
|
|
66
|
+
let aValue = formatString(nodeValueGetter(aNode))
|
|
67
|
+
let bValue = formatString(nodeValueGetter(bNode))
|
|
68
|
+
for (let i = 0; i < aValue.length; i++) {
|
|
69
|
+
let aCharacter = aValue[i]
|
|
70
|
+
let bCharacter = bValue[i]
|
|
71
|
+
let indexOfA = indexByCharacters.get(aCharacter)
|
|
72
|
+
let indexOfB = indexByCharacters.get(bCharacter)
|
|
73
|
+
indexOfA ?? (indexOfA = Infinity)
|
|
74
|
+
indexOfB ?? (indexOfB = Infinity)
|
|
75
|
+
if (indexOfA !== indexOfB) {
|
|
76
|
+
return convertBooleanToSign.convertBooleanToSign(
|
|
77
|
+
indexOfA - indexOfB > 0,
|
|
78
|
+
)
|
|
45
79
|
}
|
|
46
|
-
return aSize - bSize
|
|
47
80
|
}
|
|
81
|
+
return 0
|
|
48
82
|
}
|
|
49
|
-
return orderCoefficient * sortingFunction(a, b)
|
|
50
83
|
}
|
|
84
|
+
let getLineLengthSortingFunction =
|
|
85
|
+
({ maxLineLength }, nodeValueGetter) =>
|
|
86
|
+
(aNode, bNode) => {
|
|
87
|
+
let aSize = aNode.size
|
|
88
|
+
let bSize = bNode.size
|
|
89
|
+
if (maxLineLength) {
|
|
90
|
+
let isTooLong = (size, node) =>
|
|
91
|
+
size > maxLineLength && node.hasMultipleImportDeclarations
|
|
92
|
+
if (isTooLong(aSize, aNode)) {
|
|
93
|
+
aSize = nodeValueGetter(aNode).length + 10
|
|
94
|
+
}
|
|
95
|
+
if (isTooLong(bSize, bNode)) {
|
|
96
|
+
bSize = nodeValueGetter(bNode).length + 10
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return aSize - bSize
|
|
100
|
+
}
|
|
51
101
|
let getFormatStringFunction = (ignoreCase, specialCharacters) => value => {
|
|
52
102
|
let valueToCompare = value
|
|
53
103
|
if (ignoreCase) {
|
|
@@ -22,6 +22,7 @@ let getCustomGroupsCompareOptions = (options, groupNumber) => {
|
|
|
22
22
|
specialCharacters: options.specialCharacters,
|
|
23
23
|
type: (customGroup == null ? void 0 : customGroup.type) ?? options.type,
|
|
24
24
|
ignoreCase: options.ignoreCase,
|
|
25
|
+
alphabet: options.alphabet,
|
|
25
26
|
locales: options.locales,
|
|
26
27
|
}
|
|
27
28
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' })
|
|
3
|
+
const matches = require('./matches.js')
|
|
4
|
+
let getMatchingContextOptions = ({ contextOptions, nodeNames }) =>
|
|
5
|
+
contextOptions.find(options => {
|
|
6
|
+
var _a
|
|
7
|
+
let allNamesMatchPattern =
|
|
8
|
+
(_a = options.useConfigurationIf) == null
|
|
9
|
+
? void 0
|
|
10
|
+
: _a.allNamesMatchPattern
|
|
11
|
+
return (
|
|
12
|
+
!allNamesMatchPattern ||
|
|
13
|
+
nodeNames.every(nodeName =>
|
|
14
|
+
matches.matches(nodeName, allNamesMatchPattern),
|
|
15
|
+
)
|
|
16
|
+
)
|
|
17
|
+
})
|
|
18
|
+
exports.getMatchingContextOptions = getMatchingContextOptions
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' })
|
|
3
|
+
let isNodeFunctionType = node => {
|
|
4
|
+
if (node.type === 'TSMethodSignature' || node.type === 'TSFunctionType') {
|
|
5
|
+
return true
|
|
6
|
+
}
|
|
7
|
+
if (node.type === 'TSUnionType' || node.type === 'TSIntersectionType') {
|
|
8
|
+
return node.types.every(isNodeFunctionType)
|
|
9
|
+
}
|
|
10
|
+
if (node.type === 'TSPropertySignature' && node.typeAnnotation) {
|
|
11
|
+
return isNodeFunctionType(node.typeAnnotation.typeAnnotation)
|
|
12
|
+
}
|
|
13
|
+
return false
|
|
14
|
+
}
|
|
15
|
+
exports.isNodeFunctionType = isNodeFunctionType
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' })
|
|
3
|
+
let validateCustomSortConfiguration = ({ alphabet, type }) => {
|
|
4
|
+
if (type !== 'custom') {
|
|
5
|
+
return
|
|
6
|
+
}
|
|
7
|
+
if (!alphabet.length) {
|
|
8
|
+
throw new Error('`alphabet` option must not be empty')
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
exports.validateCustomSortConfiguration = validateCustomSortConfiguration
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' })
|
|
3
|
-
const validateGroupsConfiguration = require('
|
|
3
|
+
const validateGroupsConfiguration = require('./validate-groups-configuration.js')
|
|
4
4
|
let validateGeneratedGroupsConfiguration = ({
|
|
5
5
|
customGroups,
|
|
6
6
|
selectors,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-perfectionist",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.3.0",
|
|
4
4
|
"description": "ESLint plugin for sorting various data such as objects, imports, types, enums, JSX props, etc.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"eslint",
|
|
@@ -17,14 +17,18 @@
|
|
|
17
17
|
"types": "./dist/index.d.ts",
|
|
18
18
|
"default": "./dist/index.js"
|
|
19
19
|
},
|
|
20
|
+
"./alphabet": {
|
|
21
|
+
"types": "./dist/alphabet.d.ts",
|
|
22
|
+
"default": "./dist/utils/alphabet.js"
|
|
23
|
+
},
|
|
20
24
|
"./package.json": "./package.json"
|
|
21
25
|
},
|
|
22
26
|
"files": [
|
|
23
27
|
"./dist"
|
|
24
28
|
],
|
|
25
29
|
"dependencies": {
|
|
26
|
-
"@typescript-eslint/types": "^8.
|
|
27
|
-
"@typescript-eslint/utils": "^8.
|
|
30
|
+
"@typescript-eslint/types": "^8.18.0",
|
|
31
|
+
"@typescript-eslint/utils": "^8.18.0",
|
|
28
32
|
"natural-orderby": "^5.0.0"
|
|
29
33
|
},
|
|
30
34
|
"peerDependencies": {
|
package/readme.md
CHANGED
|
@@ -165,6 +165,7 @@ module.exports = {
|
|
|
165
165
|
| [recommended-alphabetical](https://perfectionist.dev/configs/recommended-alphabetical) | All plugin rules with alphabetical sorting in ascending order |
|
|
166
166
|
| [recommended-natural](https://perfectionist.dev/configs/recommended-natural) | All plugin rules with natural sorting in ascending order |
|
|
167
167
|
| [recommended-line-length](https://perfectionist.dev/configs/recommended-line-length) | All plugin rules with sorting by line length in descending order |
|
|
168
|
+
| [recommended-custom](https://perfectionist.dev/configs/recommended-custom) | All plugin rules with sorting by your own custom order |
|
|
168
169
|
|
|
169
170
|
## Rules
|
|
170
171
|
|
|
@@ -201,15 +202,15 @@ module.exports = {
|
|
|
201
202
|
|
|
202
203
|
### Can I automatically fix problems in the editor?
|
|
203
204
|
|
|
204
|
-
Yes. To do this, you need to enable autofix in ESLint when you save the file in your editor.
|
|
205
|
+
Yes. To do this, you need to enable autofix in ESLint when you save the file in your editor. You may find instructions for your editor can be found [here](https://perfectionist.dev/guide/integrations).
|
|
205
206
|
|
|
206
207
|
### Is it safe?
|
|
207
208
|
|
|
208
|
-
|
|
209
|
+
Overall, yes. We want to make sure that the work of the plugin does not negatively affect the behavior of the code. For example, the plugin takes into account spread operators in JSX and objects, comments to the code. Safety is our priority. If you encounter any problem, you can create an [issue](https://github.com/azat-io/eslint-plugin-perfectionist/issues/new/choose).
|
|
209
210
|
|
|
210
211
|
### Why not Prettier?
|
|
211
212
|
|
|
212
|
-
I love Prettier. However, this is not
|
|
213
|
+
I love Prettier. However, this is not its area of responsibility. Prettier is used for formatting, and ESLint is also used for styling. For example, changing the order of imports can affect how the code works (console.log calls, fetch, style loading). Prettier should not change the AST. There is a cool article about this: ["The Blurry Line Between Formatting and Style"](https://blog.joshuakgoldberg.com/the-blurry-line-between-formatting-and-style) by **@joshuakgoldberg**.
|
|
213
214
|
|
|
214
215
|
## Versioning Policy
|
|
215
216
|
|