eslint-plugin-perfectionist 4.5.0 → 4.6.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/rules/sort-imports.js +1 -1
- package/dist/rules/sort-objects/get-first-node-parent-with-type.js +4 -1
- package/dist/rules/sort-objects.js +22 -8
- package/dist/utils/common-json-schemas.js +11 -5
- package/dist/utils/get-newlines-between-option.js +23 -16
- package/dist/utils/get-options-with-clean-groups.js +2 -2
- package/dist/utils/validate-generated-groups-configuration.js +1 -0
- package/dist/utils/validate-groups-configuration.js +23 -3
- package/dist/utils/validate-newlines-and-partition-configuration.js +13 -1
- package/package.json +1 -1
|
@@ -97,7 +97,7 @@ const sortImports = createEslintRule.createEslintRule({
|
|
|
97
97
|
})
|
|
98
98
|
: null
|
|
99
99
|
let isSideEffectOnlyGroup = group => {
|
|
100
|
-
if (!group) {
|
|
100
|
+
if (!group || (typeof group === 'object' && 'newlinesBetween' in group)) {
|
|
101
101
|
return false
|
|
102
102
|
}
|
|
103
103
|
if (typeof group === 'string') {
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' })
|
|
3
|
-
let getFirstNodeParentWithType = ({ allowedTypes, node }) => {
|
|
3
|
+
let getFirstNodeParentWithType = ({ onlyFirstParent, allowedTypes, node }) => {
|
|
4
4
|
let { parent } = node
|
|
5
|
+
if (onlyFirstParent) {
|
|
6
|
+
return parent && allowedTypes.includes(parent.type) ? parent : null
|
|
7
|
+
}
|
|
5
8
|
while (parent) {
|
|
6
9
|
if (allowedTypes.includes(parent.type)) {
|
|
7
10
|
return parent
|
|
@@ -55,7 +55,10 @@ const sortObjects = createEslintRule.createEslintRule({
|
|
|
55
55
|
if (!isSortable.isSortable(nodeObject.properties)) {
|
|
56
56
|
return
|
|
57
57
|
}
|
|
58
|
-
let objectParent = getObjectParent({
|
|
58
|
+
let objectParent = getObjectParent({
|
|
59
|
+
onlyFirstParent: true,
|
|
60
|
+
node: nodeObject,
|
|
61
|
+
})
|
|
59
62
|
let matchedContextOptions = getMatchingContextOptions
|
|
60
63
|
.getMatchingContextOptions({
|
|
61
64
|
nodeNames: nodeObject.properties
|
|
@@ -114,10 +117,16 @@ const sortObjects = createEslintRule.createEslintRule({
|
|
|
114
117
|
} else if (options.destructureOnly || !options.objectDeclarations) {
|
|
115
118
|
return
|
|
116
119
|
}
|
|
120
|
+
let objectParentForIgnorePattern = getObjectParent({
|
|
121
|
+
onlyFirstParent: false,
|
|
122
|
+
node: nodeObject,
|
|
123
|
+
})
|
|
117
124
|
if (
|
|
118
|
-
(
|
|
125
|
+
(objectParentForIgnorePattern == null
|
|
126
|
+
? void 0
|
|
127
|
+
: objectParentForIgnorePattern.name) &&
|
|
119
128
|
options.ignorePattern.some(pattern =>
|
|
120
|
-
matches.matches(
|
|
129
|
+
matches.matches(objectParentForIgnorePattern.name, pattern),
|
|
121
130
|
)
|
|
122
131
|
) {
|
|
123
132
|
return
|
|
@@ -501,15 +510,18 @@ let getNodeName = ({ sourceCode, property }) => {
|
|
|
501
510
|
}
|
|
502
511
|
return sourceCode.getText(property.key)
|
|
503
512
|
}
|
|
504
|
-
let getObjectParent = ({ node }) => {
|
|
505
|
-
let variableParentName = getVariableParentName({ node })
|
|
513
|
+
let getObjectParent = ({ onlyFirstParent, node }) => {
|
|
514
|
+
let variableParentName = getVariableParentName({ onlyFirstParent, node })
|
|
506
515
|
if (variableParentName) {
|
|
507
516
|
return {
|
|
508
517
|
type: 'VariableDeclarator',
|
|
509
518
|
name: variableParentName,
|
|
510
519
|
}
|
|
511
520
|
}
|
|
512
|
-
let callParentName = getCallExpressionParentName({
|
|
521
|
+
let callParentName = getCallExpressionParentName({
|
|
522
|
+
onlyFirstParent,
|
|
523
|
+
node,
|
|
524
|
+
})
|
|
513
525
|
if (callParentName) {
|
|
514
526
|
return {
|
|
515
527
|
type: 'CallExpression',
|
|
@@ -518,12 +530,13 @@ let getObjectParent = ({ node }) => {
|
|
|
518
530
|
}
|
|
519
531
|
return null
|
|
520
532
|
}
|
|
521
|
-
let getVariableParentName = ({ node }) => {
|
|
533
|
+
let getVariableParentName = ({ onlyFirstParent, node }) => {
|
|
522
534
|
let variableParent = getFirstNodeParentWithType.getFirstNodeParentWithType({
|
|
523
535
|
allowedTypes: [
|
|
524
536
|
types.TSESTree.AST_NODE_TYPES.VariableDeclarator,
|
|
525
537
|
types.TSESTree.AST_NODE_TYPES.Property,
|
|
526
538
|
],
|
|
539
|
+
onlyFirstParent,
|
|
527
540
|
node,
|
|
528
541
|
})
|
|
529
542
|
if (!variableParent) {
|
|
@@ -539,9 +552,10 @@ let getVariableParentName = ({ node }) => {
|
|
|
539
552
|
}
|
|
540
553
|
return parentId.type === 'Identifier' ? parentId.name : null
|
|
541
554
|
}
|
|
542
|
-
let getCallExpressionParentName = ({ node }) => {
|
|
555
|
+
let getCallExpressionParentName = ({ onlyFirstParent, node }) => {
|
|
543
556
|
let callParent = getFirstNodeParentWithType.getFirstNodeParentWithType({
|
|
544
557
|
allowedTypes: [types.TSESTree.AST_NODE_TYPES.CallExpression],
|
|
558
|
+
onlyFirstParent,
|
|
545
559
|
node,
|
|
546
560
|
})
|
|
547
561
|
if (!callParent) {
|
|
@@ -45,6 +45,11 @@ let specialCharactersJsonSchema = {
|
|
|
45
45
|
enum: ['remove', 'trim', 'keep'],
|
|
46
46
|
type: 'string',
|
|
47
47
|
}
|
|
48
|
+
let newlinesBetweenJsonSchema = {
|
|
49
|
+
description: 'Specifies how new lines should be handled between groups.',
|
|
50
|
+
enum: ['ignore', 'always', 'never'],
|
|
51
|
+
type: 'string',
|
|
52
|
+
}
|
|
48
53
|
let groupsJsonSchema = {
|
|
49
54
|
items: {
|
|
50
55
|
oneOf: [
|
|
@@ -57,6 +62,12 @@ let groupsJsonSchema = {
|
|
|
57
62
|
},
|
|
58
63
|
type: 'array',
|
|
59
64
|
},
|
|
65
|
+
{
|
|
66
|
+
properties: {
|
|
67
|
+
newlinesBetween: newlinesBetweenJsonSchema,
|
|
68
|
+
},
|
|
69
|
+
type: 'object',
|
|
70
|
+
},
|
|
60
71
|
],
|
|
61
72
|
},
|
|
62
73
|
description: 'Specifies the order of the groups.',
|
|
@@ -114,11 +125,6 @@ let partitionByNewLineJsonSchema = {
|
|
|
114
125
|
'Allows to use newlines to separate the nodes into logical groups.',
|
|
115
126
|
type: 'boolean',
|
|
116
127
|
}
|
|
117
|
-
let newlinesBetweenJsonSchema = {
|
|
118
|
-
description: 'Specifies how new lines should be handled between groups.',
|
|
119
|
-
enum: ['ignore', 'always', 'never'],
|
|
120
|
-
type: 'string',
|
|
121
|
-
}
|
|
122
128
|
let buildUseConfigurationIfJsonSchema = ({ additionalProperties } = {}) => ({
|
|
123
129
|
properties: {
|
|
124
130
|
allNamesMatchPattern: {
|
|
@@ -15,26 +15,33 @@ let getNewlinesBetweenOption = ({ nextSortingNode, sortingNode, options }) => {
|
|
|
15
15
|
nextNodeGroupNumber,
|
|
16
16
|
nodeGroupNumber,
|
|
17
17
|
})
|
|
18
|
-
if (!options.customGroups || !Array.isArray(options.customGroups)) {
|
|
19
|
-
return globalNewlinesBetweenOption
|
|
20
|
-
}
|
|
21
18
|
let nodeGroup = options.groups[nodeGroupNumber]
|
|
22
19
|
let nextNodeGroup = options.groups[nextNodeGroupNumber]
|
|
23
|
-
if (Array.isArray(nodeGroup) || Array.isArray(nextNodeGroup)) {
|
|
24
|
-
return globalNewlinesBetweenOption
|
|
25
|
-
}
|
|
26
|
-
let nodeCustomGroup = options.customGroups.find(
|
|
27
|
-
customGroup => customGroup.groupName === nodeGroup,
|
|
28
|
-
)
|
|
29
|
-
let nextNodeCustomGroup = options.customGroups.find(
|
|
30
|
-
customGroup => customGroup.groupName === nextNodeGroup,
|
|
31
|
-
)
|
|
32
20
|
if (
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
21
|
+
Array.isArray(options.customGroups) &&
|
|
22
|
+
typeof nodeGroup === 'string' &&
|
|
23
|
+
typeof nextNodeGroup === 'string' &&
|
|
24
|
+
nodeGroup === nextNodeGroup
|
|
36
25
|
) {
|
|
37
|
-
|
|
26
|
+
let nodeCustomGroup = options.customGroups.find(
|
|
27
|
+
customGroup => customGroup.groupName === nodeGroup,
|
|
28
|
+
)
|
|
29
|
+
let nextNodeCustomGroup = options.customGroups.find(
|
|
30
|
+
customGroup => customGroup.groupName === nextNodeGroup,
|
|
31
|
+
)
|
|
32
|
+
if (
|
|
33
|
+
nodeCustomGroup &&
|
|
34
|
+
nextNodeCustomGroup &&
|
|
35
|
+
nodeCustomGroup.groupName === nextNodeCustomGroup.groupName
|
|
36
|
+
) {
|
|
37
|
+
return nodeCustomGroup.newlinesInside ?? globalNewlinesBetweenOption
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
if (nextNodeGroupNumber === nodeGroupNumber + 2) {
|
|
41
|
+
let groupBetween = options.groups[nodeGroupNumber + 1]
|
|
42
|
+
if (typeof groupBetween === 'object' && 'newlinesBetween' in groupBetween) {
|
|
43
|
+
return groupBetween.newlinesBetween
|
|
44
|
+
}
|
|
38
45
|
}
|
|
39
46
|
return globalNewlinesBetweenOption
|
|
40
47
|
}
|
|
@@ -3,9 +3,9 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' })
|
|
|
3
3
|
let getOptionsWithCleanGroups = options => ({
|
|
4
4
|
...options,
|
|
5
5
|
groups: options.groups
|
|
6
|
-
.filter(group => group.length > 0)
|
|
6
|
+
.filter(group => !Array.isArray(group) || group.length > 0)
|
|
7
7
|
.map(group =>
|
|
8
|
-
|
|
8
|
+
Array.isArray(group) ? getCleanedNestedGroups(group) : group,
|
|
9
9
|
),
|
|
10
10
|
})
|
|
11
11
|
let getCleanedNestedGroups = nestedGroup =>
|
|
@@ -9,9 +9,26 @@ let validateGroupsConfiguration = (
|
|
|
9
9
|
...allowedPredefinedGroups,
|
|
10
10
|
...allowedCustomGroups,
|
|
11
11
|
])
|
|
12
|
-
let invalidGroups =
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
let invalidGroups = []
|
|
13
|
+
let isPreviousElementNewlinesBetween = false
|
|
14
|
+
for (let groupElement of groups) {
|
|
15
|
+
if (typeof groupElement === 'object' && 'newlinesBetween' in groupElement) {
|
|
16
|
+
if (isPreviousElementNewlinesBetween) {
|
|
17
|
+
throw new Error("Consecutive 'newlinesBetween' objects are not allowed")
|
|
18
|
+
}
|
|
19
|
+
isPreviousElementNewlinesBetween = true
|
|
20
|
+
} else {
|
|
21
|
+
isPreviousElementNewlinesBetween = false
|
|
22
|
+
let groupElements = Array.isArray(groupElement)
|
|
23
|
+
? groupElement
|
|
24
|
+
: [groupElement]
|
|
25
|
+
for (let group of groupElements) {
|
|
26
|
+
if (!allowedGroupsSet.has(group)) {
|
|
27
|
+
invalidGroups.push(group)
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
15
32
|
if (invalidGroups.length) {
|
|
16
33
|
throw new Error(`Invalid group(s): ${invalidGroups.join(', ')}`)
|
|
17
34
|
}
|
|
@@ -22,6 +39,9 @@ let validateNoDuplicatedGroups = groups => {
|
|
|
22
39
|
let seenGroups = /* @__PURE__ */ new Set()
|
|
23
40
|
let duplicatedGroups = /* @__PURE__ */ new Set()
|
|
24
41
|
for (let group of flattenGroups) {
|
|
42
|
+
if (typeof group === 'object' && 'newlinesBetween' in group) {
|
|
43
|
+
continue
|
|
44
|
+
}
|
|
25
45
|
if (seenGroups.has(group)) {
|
|
26
46
|
duplicatedGroups.add(group)
|
|
27
47
|
} else {
|
|
@@ -3,12 +3,24 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' })
|
|
|
3
3
|
let validateNewlinesAndPartitionConfiguration = ({
|
|
4
4
|
partitionByNewLine,
|
|
5
5
|
newlinesBetween,
|
|
6
|
+
groups,
|
|
6
7
|
}) => {
|
|
7
|
-
if (
|
|
8
|
+
if (!partitionByNewLine) {
|
|
9
|
+
return
|
|
10
|
+
}
|
|
11
|
+
if (newlinesBetween !== 'ignore') {
|
|
8
12
|
throw new Error(
|
|
9
13
|
"The 'partitionByNewLine' and 'newlinesBetween' options cannot be used together",
|
|
10
14
|
)
|
|
11
15
|
}
|
|
16
|
+
let hasNewlinesBetweenGroup = groups.some(
|
|
17
|
+
group => typeof group === 'object' && 'newlinesBetween' in group,
|
|
18
|
+
)
|
|
19
|
+
if (hasNewlinesBetweenGroup) {
|
|
20
|
+
throw new Error(
|
|
21
|
+
"'newlinesBetween' objects can not be used in 'groups' alongside 'partitionByNewLine'",
|
|
22
|
+
)
|
|
23
|
+
}
|
|
12
24
|
}
|
|
13
25
|
exports.validateNewlinesAndPartitionConfiguration =
|
|
14
26
|
validateNewlinesAndPartitionConfiguration
|