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.
@@ -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({ node: nodeObject })
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
- (objectParent == null ? void 0 : objectParent.name) &&
125
+ (objectParentForIgnorePattern == null
126
+ ? void 0
127
+ : objectParentForIgnorePattern.name) &&
119
128
  options.ignorePattern.some(pattern =>
120
- matches.matches(objectParent.name, pattern),
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({ node })
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
- nodeCustomGroup &&
34
- nextNodeCustomGroup &&
35
- nodeCustomGroup.groupName === nextNodeCustomGroup.groupName
21
+ Array.isArray(options.customGroups) &&
22
+ typeof nodeGroup === 'string' &&
23
+ typeof nextNodeGroup === 'string' &&
24
+ nodeGroup === nextNodeGroup
36
25
  ) {
37
- return nodeCustomGroup.newlinesInside ?? globalNewlinesBetweenOption
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
- typeof group === 'string' ? group : getCleanedNestedGroups(group),
8
+ Array.isArray(group) ? getCleanedNestedGroups(group) : group,
9
9
  ),
10
10
  })
11
11
  let getCleanedNestedGroups = nestedGroup =>
@@ -14,6 +14,7 @@ let validateGeneratedGroupsConfiguration = ({
14
14
  )
15
15
  let invalidGroups = groups
16
16
  .flat()
17
+ .filter(group => typeof group === 'string')
17
18
  .filter(
18
19
  group =>
19
20
  !isPredefinedGroup(selectors, modifiers, group) &&
@@ -9,9 +9,26 @@ let validateGroupsConfiguration = (
9
9
  ...allowedPredefinedGroups,
10
10
  ...allowedCustomGroups,
11
11
  ])
12
- let invalidGroups = groups
13
- .flat()
14
- .filter(group => !allowedGroupsSet.has(group))
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 (!!partitionByNewLine && newlinesBetween !== 'ignore') {
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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-perfectionist",
3
- "version": "4.5.0",
3
+ "version": "4.6.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",