eslint-plugin-perfectionist 4.2.0 → 4.4.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.
Files changed (42) hide show
  1. package/dist/alphabet.d.ts +176 -0
  2. package/dist/index.d.ts +2 -0
  3. package/dist/index.js +8 -0
  4. package/dist/rules/sort-array-includes-utils.js +30 -0
  5. package/dist/rules/sort-array-includes.js +150 -54
  6. package/dist/rules/sort-array-includes.types.js +10 -0
  7. package/dist/rules/sort-classes.js +19 -16
  8. package/dist/rules/sort-decorators.js +11 -6
  9. package/dist/rules/sort-enums.js +39 -31
  10. package/dist/rules/sort-exports.js +11 -5
  11. package/dist/rules/sort-heritage-clauses.js +12 -6
  12. package/dist/rules/sort-imports.js +34 -21
  13. package/dist/rules/sort-interfaces.js +3 -1
  14. package/dist/rules/sort-intersection-types.js +24 -19
  15. package/dist/rules/sort-jsx-props.js +12 -7
  16. package/dist/rules/sort-maps.js +18 -13
  17. package/dist/rules/sort-modules.js +23 -18
  18. package/dist/rules/sort-named-exports.js +18 -13
  19. package/dist/rules/sort-named-imports.js +18 -13
  20. package/dist/rules/sort-object-types.js +149 -103
  21. package/dist/rules/sort-objects.js +142 -58
  22. package/dist/rules/sort-sets.js +14 -5
  23. package/dist/rules/sort-switch-case.js +16 -14
  24. package/dist/rules/sort-union-types.js +24 -19
  25. package/dist/rules/sort-variable-declarations.js +18 -13
  26. package/dist/utils/alphabet.js +385 -0
  27. package/dist/utils/common-json-schemas.js +27 -5
  28. package/dist/utils/compare.js +88 -38
  29. package/dist/utils/convert-boolean-to-sign.js +4 -0
  30. package/dist/utils/create-node-index-map.js +10 -0
  31. package/dist/{rules → utils}/get-custom-groups-compare-options.js +1 -0
  32. package/dist/utils/{get-node-parent.js → get-first-node-parent-with-type.js} +3 -4
  33. package/dist/utils/get-matching-context-options.js +18 -0
  34. package/dist/utils/get-settings.js +1 -0
  35. package/dist/utils/is-node-function-type.js +15 -0
  36. package/dist/utils/is-partition-comment.js +4 -1
  37. package/dist/utils/pairwise.js +1 -3
  38. package/dist/utils/validate-custom-sort-configuration.js +11 -0
  39. package/dist/{rules → utils}/validate-generated-groups-configuration.js +1 -1
  40. package/dist/utils/validate-groups-configuration.js +11 -5
  41. package/package.json +7 -3
  42. package/readme.md +4 -3
@@ -0,0 +1,176 @@
1
+ /**
2
+ * Utility class to build alphabets
3
+ */
4
+ export declare class Alphabet {
5
+ private _characters
6
+ private constructor()
7
+ /**
8
+ * Generates an alphabet from the given characters.
9
+ * @param {string|string[]} values - The characters to generate the alphabet from
10
+ * @returns {Alphabet} - The wrapped alphabet
11
+ */
12
+ static generateFrom(values: string[] | string): Alphabet
13
+ /**
14
+ * Generates an alphabet containing relevant characters from the Unicode
15
+ * standard. Contains the Unicode planes 0 and 1.
16
+ * @returns {Alphabet} - The generated alphabet
17
+ */
18
+ static generateRecommendedAlphabet(): Alphabet
19
+ /**
20
+ * Generates an alphabet containing all characters from the Unicode standard
21
+ * except for irrelevant Unicode planes.
22
+ * Contains the Unicode planes 0, 1, 2 and 3.
23
+ * @returns {Alphabet} - The generated alphabet
24
+ */
25
+ static generateCompleteAlphabet(): Alphabet
26
+ private static _convertCodepointToCharacter
27
+ /**
28
+ * Generates an alphabet containing relevant characters from the Unicode
29
+ * standard.
30
+ * @param {number} maxCodePoint - The maximum code point to generate the
31
+ * alphabet to
32
+ * @returns {Alphabet} - The generated alphabet
33
+ */
34
+ private static _generateAlphabetToRange
35
+ /**
36
+ * For each character with a lower and upper case, permutes the two cases
37
+ * so that the alphabet is ordered by the case priority entered.
38
+ * @param {string} casePriority - The case to prioritize
39
+ * @returns {Alphabet} - The same alphabet instance with the cases prioritized
40
+ * @example
41
+ * Alphabet.generateFrom('aAbBcdCD')
42
+ * .prioritizeCase('uppercase')
43
+ * // Returns 'AaBbCDcd'
44
+ */
45
+ prioritizeCase(casePriority: 'lowercase' | 'uppercase'): this
46
+ /**
47
+ * Adds specific characters to the end of the alphabet.
48
+ * @param {string|string[]} values - The characters to push to the alphabet
49
+ * @returns {Alphabet} - The same alphabet instance without the specified
50
+ * characters
51
+ * @example
52
+ * Alphabet.generateFrom('ab')
53
+ * .pushCharacters('cd')
54
+ * // Returns 'abcd'
55
+ */
56
+ pushCharacters(values: string[] | string): this
57
+ /**
58
+ * Permutes characters with cases so that all characters with the entered case
59
+ * are put before the other characters.
60
+ * @param {string} caseToComeFirst - The case to put before the other
61
+ * characters
62
+ * @returns {Alphabet} - The same alphabet instance with all characters with
63
+ * case before all the characters with the other case
64
+ */
65
+ placeAllWithCaseBeforeAllWithOtherCase(
66
+ caseToComeFirst: 'uppercase' | 'lowercase',
67
+ ): this
68
+ /**
69
+ * Places a specific character right before another character in the alphabet.
70
+ * @param {object} params - The parameters for the operation
71
+ * @param {string} params.characterBefore - The character to come before
72
+ * characterAfter
73
+ * @param {string} params.characterAfter - The target character
74
+ * @returns {Alphabet} - The same alphabet instance with the specific
75
+ * character prioritized
76
+ * @example
77
+ * Alphabet.generateFrom('ab-cd/')
78
+ * .placeCharacterBefore({ characterBefore: '/', characterAfter: '-' })
79
+ * // Returns 'ab/-cd'
80
+ */
81
+ placeCharacterBefore({
82
+ characterBefore,
83
+ characterAfter,
84
+ }: {
85
+ characterBefore: string
86
+ characterAfter: string
87
+ }): this
88
+ /**
89
+ * Places a specific character right after another character in the alphabet.
90
+ * @param {object} params - The parameters for the operation
91
+ * @param {string} params.characterBefore - The target character
92
+ * @param {string} params.characterAfter - The character to come after
93
+ * characterBefore
94
+ * @returns {Alphabet} - The same alphabet instance with the specific
95
+ * character prioritized
96
+ * @example
97
+ * Alphabet.generateFrom('ab-cd/')
98
+ * .placeCharacterAfter({ characterBefore: '/', characterAfter: '-' })
99
+ * // Returns 'abcd/-'
100
+ */
101
+ placeCharacterAfter({
102
+ characterBefore,
103
+ characterAfter,
104
+ }: {
105
+ characterBefore: string
106
+ characterAfter: string
107
+ }): this
108
+ /**
109
+ * Removes specific characters from the alphabet by their range.
110
+ * @param {object} range - The Unicode range to remove characters from
111
+ * @param {number} range.start - The starting Unicode codepoint
112
+ * @param {number} range.end - The ending Unicode codepoint
113
+ * @returns {Alphabet} - The same alphabet instance without the characters
114
+ * from the specified range
115
+ */
116
+ removeUnicodeRange({ start, end }: { start: number; end: number }): this
117
+ /**
118
+ * Sorts the alphabet by the sorting function provided.
119
+ * @param {Function} sortingFunction - The sorting function to use
120
+ * @returns {Alphabet} - The same alphabet instance sorted by the sorting function provided
121
+ */
122
+ sortBy(
123
+ sortingFunction: (characterA: string, characterB: string) => number,
124
+ ): this
125
+ /**
126
+ * Removes specific characters from the alphabet.
127
+ * @param {string|string[]} values - The characters to remove from the
128
+ * alphabet
129
+ * @returns {Alphabet} - The same alphabet instance without the specified
130
+ * characters
131
+ * @example
132
+ * Alphabet.generateFrom('abcd')
133
+ * .removeCharacters('dcc')
134
+ * // Returns 'ab'
135
+ */
136
+ removeCharacters(values: string[] | string): this
137
+ /**
138
+ * Sorts the alphabet by the natural order of the characters using
139
+ * `natural-orderby`.
140
+ * @param {string} locale - The locale to use for sorting
141
+ * @returns {Alphabet} - The same alphabet instance sorted by the natural
142
+ * order of the characters
143
+ */
144
+ sortByNaturalSort(locale?: string): this
145
+ /**
146
+ * Sorts the alphabet by the character code point.
147
+ * @returns {Alphabet} - The same alphabet instance sorted by the character
148
+ * code point
149
+ */
150
+ sortByCharCodeAt(): this
151
+ /**
152
+ * Sorts the alphabet by the locale order of the characters.
153
+ * @param {Intl.LocalesArgument} locales - The locales to use for sorting
154
+ * @returns {Alphabet} - The same alphabet instance sorted by the locale
155
+ * order of the characters
156
+ */
157
+ sortByLocaleCompare(locales?: Intl.LocalesArgument): this
158
+ /**
159
+ * Retrieves the characters from the alphabet.
160
+ * @returns {string} The characters from the alphabet
161
+ */
162
+ getCharacters(): string
163
+ /**
164
+ * Reverses the alphabet.
165
+ * @returns {Alphabet} - The same alphabet instance reversed
166
+ * @example
167
+ * Alphabet.generateFrom('ab')
168
+ * .reverse()
169
+ * // Returns 'ba'
170
+ */
171
+ reverse(): this
172
+ private _placeCharacterBeforeOrAfter
173
+ private _getCharactersWithCase
174
+ }
175
+
176
+ export {}
package/dist/index.d.ts CHANGED
@@ -30,9 +30,11 @@ declare interface PluginConfig {
30
30
  'recommended-alphabetical-legacy': Linter.LegacyConfig
31
31
  'recommended-line-length-legacy': Linter.LegacyConfig
32
32
  'recommended-natural-legacy': Linter.LegacyConfig
33
+ 'recommended-custom-legacy': Linter.LegacyConfig
33
34
  'recommended-alphabetical': Linter.Config
34
35
  'recommended-line-length': Linter.Config
35
36
  'recommended-natural': Linter.Config
37
+ 'recommended-custom': Linter.Config
36
38
  }
37
39
  name: string
38
40
  }
package/dist/index.js CHANGED
@@ -77,6 +77,10 @@ const index = {
77
77
  type: 'natural',
78
78
  order: 'asc',
79
79
  }),
80
+ 'recommended-custom-legacy': createLegacyConfig({
81
+ type: 'custom',
82
+ order: 'asc',
83
+ }),
80
84
  'recommended-alphabetical': createConfig({
81
85
  type: 'alphabetical',
82
86
  order: 'asc',
@@ -89,6 +93,10 @@ const index = {
89
93
  type: 'natural',
90
94
  order: 'asc',
91
95
  }),
96
+ 'recommended-custom': createConfig({
97
+ type: 'custom',
98
+ order: 'asc',
99
+ }),
92
100
  },
93
101
  }
94
102
  module.exports = index
@@ -0,0 +1,30 @@
1
+ 'use strict'
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' })
3
+ const matches = require('../utils/matches.js')
4
+ let customGroupMatches = props => {
5
+ if ('anyOf' in props.customGroup) {
6
+ return props.customGroup.anyOf.some(subgroup =>
7
+ customGroupMatches({ ...props, customGroup: subgroup }),
8
+ )
9
+ }
10
+ if (
11
+ props.customGroup.selector &&
12
+ !props.selectors.includes(props.customGroup.selector)
13
+ ) {
14
+ return false
15
+ }
16
+ if (
17
+ 'elementNamePattern' in props.customGroup &&
18
+ props.customGroup.elementNamePattern
19
+ ) {
20
+ let matchesElementNamePattern = matches.matches(
21
+ props.elementName,
22
+ props.customGroup.elementNamePattern,
23
+ )
24
+ if (!matchesElementNamePattern) {
25
+ return false
26
+ }
27
+ }
28
+ return true
29
+ }
30
+ exports.customGroupMatches = customGroupMatches
@@ -4,56 +4,77 @@ Object.defineProperties(exports, {
4
4
  [Symbol.toStringTag]: { value: 'Module' },
5
5
  })
6
6
  const commonJsonSchemas = require('../utils/common-json-schemas.js')
7
+ const validateGeneratedGroupsConfiguration = require('../utils/validate-generated-groups-configuration.js')
8
+ const getCustomGroupsCompareOptions = require('../utils/get-custom-groups-compare-options.js')
9
+ const getMatchingContextOptions = require('../utils/get-matching-context-options.js')
10
+ const generatePredefinedGroups = require('../utils/generate-predefined-groups.js')
7
11
  const getEslintDisabledLines = require('../utils/get-eslint-disabled-lines.js')
12
+ const sortArrayIncludes_types = require('./sort-array-includes.types.js')
8
13
  const isNodeEslintDisabled = require('../utils/is-node-eslint-disabled.js')
9
14
  const isPartitionComment = require('../utils/is-partition-comment.js')
15
+ const createNodeIndexMap = require('../utils/create-node-index-map.js')
16
+ const sortNodesByGroups = require('../utils/sort-nodes-by-groups.js')
10
17
  const getCommentsBefore = require('../utils/get-comments-before.js')
18
+ const sortArrayIncludesUtils = require('./sort-array-includes-utils.js')
11
19
  const createEslintRule = require('../utils/create-eslint-rule.js')
12
20
  const getLinesBetween = require('../utils/get-lines-between.js')
21
+ const getGroupNumber = require('../utils/get-group-number.js')
13
22
  const getSourceCode = require('../utils/get-source-code.js')
14
23
  const toSingleLine = require('../utils/to-single-line.js')
15
24
  const rangeToDiff = require('../utils/range-to-diff.js')
16
25
  const getSettings = require('../utils/get-settings.js')
17
26
  const isSortable = require('../utils/is-sortable.js')
18
- const sortNodes = require('../utils/sort-nodes.js')
19
27
  const makeFixes = require('../utils/make-fixes.js')
28
+ const useGroups = require('../utils/use-groups.js')
20
29
  const complete = require('../utils/complete.js')
21
30
  const pairwise = require('../utils/pairwise.js')
31
+ let cachedGroupsByModifiersAndSelectors = /* @__PURE__ */ new Map()
22
32
  let defaultOptions = {
23
33
  groupKind: 'literals-first',
24
34
  specialCharacters: 'keep',
25
35
  partitionByComment: false,
26
36
  partitionByNewLine: false,
37
+ useConfigurationIf: {},
27
38
  type: 'alphabetical',
28
39
  ignoreCase: true,
29
40
  locales: 'en-US',
41
+ customGroups: [],
42
+ alphabet: '',
30
43
  order: 'asc',
44
+ groups: [],
31
45
  }
32
46
  let jsonSchema = {
33
- properties: {
34
- partitionByComment: {
35
- ...commonJsonSchemas.partitionByCommentJsonSchema,
36
- description:
37
- 'Allows you to use comments to separate the array members into logical groups.',
47
+ items: {
48
+ properties: {
49
+ partitionByComment: {
50
+ ...commonJsonSchemas.partitionByCommentJsonSchema,
51
+ description:
52
+ 'Allows you to use comments to separate the array members into logical groups.',
53
+ },
54
+ groupKind: {
55
+ enum: ['mixed', 'literals-first', 'spreads-first'],
56
+ description: 'Specifies top-level groups.',
57
+ type: 'string',
58
+ },
59
+ customGroups: commonJsonSchemas.buildCustomGroupsArrayJsonSchema({
60
+ singleCustomGroupJsonSchema:
61
+ sortArrayIncludes_types.singleCustomGroupJsonSchema,
62
+ }),
63
+ useConfigurationIf: commonJsonSchemas.buildUseConfigurationIfJsonSchema(),
64
+ type: commonJsonSchemas.buildTypeJsonSchema({ withUnsorted: true }),
65
+ partitionByNewLine: commonJsonSchemas.partitionByNewLineJsonSchema,
66
+ specialCharacters: commonJsonSchemas.specialCharactersJsonSchema,
67
+ ignoreCase: commonJsonSchemas.ignoreCaseJsonSchema,
68
+ alphabet: commonJsonSchemas.alphabetJsonSchema,
69
+ locales: commonJsonSchemas.localesJsonSchema,
70
+ groups: commonJsonSchemas.groupsJsonSchema,
71
+ order: commonJsonSchemas.orderJsonSchema,
38
72
  },
39
- groupKind: {
40
- enum: ['mixed', 'literals-first', 'spreads-first'],
41
- description: 'Specifies top-level groups.',
42
- type: 'string',
43
- },
44
- partitionByNewLine: {
45
- description:
46
- 'Allows to use spaces to separate the nodes into logical groups.',
47
- type: 'boolean',
48
- },
49
- specialCharacters: commonJsonSchemas.specialCharactersJsonSchema,
50
- ignoreCase: commonJsonSchemas.ignoreCaseJsonSchema,
51
- locales: commonJsonSchemas.localesJsonSchema,
52
- order: commonJsonSchemas.orderJsonSchema,
53
- type: commonJsonSchemas.typeJsonSchema,
73
+ additionalProperties: false,
74
+ type: 'object',
54
75
  },
55
- additionalProperties: false,
56
- type: 'object',
76
+ uniqueItems: true,
77
+ type: 'array',
57
78
  }
58
79
  const sortArrayIncludes = createEslintRule.createEslintRule({
59
80
  create: context => ({
@@ -68,38 +89,68 @@ const sortArrayIncludes = createEslintRule.createEslintRule({
68
89
  node.object.type === 'ArrayExpression'
69
90
  ? node.object.elements
70
91
  : node.object.arguments
71
- sortArray(context, 'unexpectedArrayIncludesOrder', elements)
92
+ sortArray({
93
+ availableMessageIds: {
94
+ unexpectedGroupOrder: 'unexpectedArrayIncludesGroupOrder',
95
+ unexpectedOrder: 'unexpectedArrayIncludesOrder',
96
+ },
97
+ elements,
98
+ context,
99
+ })
72
100
  }
73
101
  },
74
102
  }),
75
103
  meta: {
104
+ messages: {
105
+ unexpectedArrayIncludesGroupOrder:
106
+ 'Expected "{{right}}" ({{rightGroup}}) to come before "{{left}}" ({{leftGroup}}).',
107
+ unexpectedArrayIncludesOrder:
108
+ 'Expected "{{right}}" to come before "{{left}}".',
109
+ },
76
110
  docs: {
77
111
  description: 'Enforce sorted arrays before include method.',
78
112
  url: 'https://perfectionist.dev/rules/sort-array-includes',
79
113
  recommended: true,
80
114
  },
81
- messages: {
82
- unexpectedArrayIncludesOrder:
83
- 'Expected "{{right}}" to come before "{{left}}".',
84
- },
85
- schema: [jsonSchema],
115
+ schema: jsonSchema,
86
116
  type: 'suggestion',
87
117
  fixable: 'code',
88
118
  },
89
119
  defaultOptions: [defaultOptions],
90
120
  name: 'sort-array-includes',
91
121
  })
92
- let sortArray = (context, messageId, elements) => {
122
+ let sortArray = ({ availableMessageIds, elements, context }) => {
93
123
  if (!isSortable.isSortable(elements)) {
94
124
  return
95
125
  }
126
+ let sourceCode = getSourceCode.getSourceCode(context)
96
127
  let settings = getSettings.getSettings(context.settings)
97
- let options = complete.complete(
98
- context.options.at(0),
128
+ let matchedContextOptions =
129
+ getMatchingContextOptions.getMatchingContextOptions({
130
+ nodeNames: elements
131
+ .filter(element => element !== null)
132
+ .map(element => getNodeName({ sourceCode, element })),
133
+ contextOptions: context.options,
134
+ })
135
+ let completeOptions = complete.complete(
136
+ matchedContextOptions[0],
99
137
  settings,
100
138
  defaultOptions,
101
139
  )
102
- let sourceCode = getSourceCode.getSourceCode(context)
140
+ let { type } = completeOptions
141
+ if (type === 'unsorted') {
142
+ return
143
+ }
144
+ let options = {
145
+ ...completeOptions,
146
+ type,
147
+ }
148
+ validateGeneratedGroupsConfiguration.validateGeneratedGroupsConfiguration({
149
+ customGroups: options.customGroups,
150
+ selectors: sortArrayIncludes_types.allSelectors,
151
+ groups: options.groups,
152
+ modifiers: [],
153
+ })
103
154
  let eslintDisabledLines = getEslintDisabledLines.getEslintDisabledLines({
104
155
  ruleName: context.id,
105
156
  sourceCode,
@@ -110,30 +161,60 @@ let sortArray = (context, messageId, elements) => {
110
161
  if (element === null) {
111
162
  return accumulator
112
163
  }
113
- let lastSortingNode =
114
- (_a = accumulator.at(-1)) == null ? void 0 : _a.at(-1)
164
+ let { defineGroup, getGroup } = useGroups.useGroups(options)
165
+ let groupKind
166
+ let selector
167
+ if (element.type === 'SpreadElement') {
168
+ groupKind = 'spread'
169
+ selector = 'spread'
170
+ } else {
171
+ groupKind = 'literal'
172
+ selector = 'literal'
173
+ }
174
+ let predefinedGroups = generatePredefinedGroups.generatePredefinedGroups({
175
+ cache: cachedGroupsByModifiersAndSelectors,
176
+ selectors: [selector],
177
+ modifiers: [],
178
+ })
179
+ for (let predefinedGroup of predefinedGroups) {
180
+ defineGroup(predefinedGroup)
181
+ }
182
+ let name = getNodeName({ sourceCode, element })
183
+ for (let customGroup of options.customGroups) {
184
+ if (
185
+ sortArrayIncludesUtils.customGroupMatches({
186
+ selectors: [selector],
187
+ elementName: name,
188
+ customGroup,
189
+ })
190
+ ) {
191
+ defineGroup(customGroup.groupName, true)
192
+ if (getGroup() === customGroup.groupName) {
193
+ break
194
+ }
195
+ }
196
+ }
115
197
  let sortingNode = {
116
- name:
117
- element.type === 'Literal'
118
- ? `${element.value}`
119
- : sourceCode.getText(element),
120
198
  isEslintDisabled: isNodeEslintDisabled.isNodeEslintDisabled(
121
199
  element,
122
200
  eslintDisabledLines,
123
201
  ),
124
- groupKind: element.type === 'SpreadElement' ? 'spread' : 'literal',
125
202
  size: rangeToDiff.rangeToDiff(element, sourceCode),
203
+ group: getGroup(),
126
204
  node: element,
205
+ groupKind,
206
+ name,
127
207
  }
208
+ let lastSortingNode =
209
+ (_a = accumulator.at(-1)) == null ? void 0 : _a.at(-1)
128
210
  if (
129
- (options.partitionByComment &&
130
- isPartitionComment.hasPartitionComment(
131
- options.partitionByComment,
132
- getCommentsBefore.getCommentsBefore({
133
- node: element,
134
- sourceCode,
135
- }),
136
- )) ||
211
+ isPartitionComment.hasPartitionComment(
212
+ options.partitionByComment,
213
+ getCommentsBefore.getCommentsBefore({
214
+ node: element,
215
+ sourceCode,
216
+ }),
217
+ ) ||
137
218
  (options.partitionByNewLine &&
138
219
  lastSortingNode &&
139
220
  getLinesBetween.getLinesBetween(
@@ -166,21 +247,29 @@ let sortArray = (context, messageId, elements) => {
166
247
  )
167
248
  let sortNodesIgnoringEslintDisabledNodes = ignoreEslintDisabledNodes =>
168
249
  filteredGroupKindNodes.flatMap(groupedNodes =>
169
- sortNodes.sortNodes(groupedNodes, options, {
250
+ sortNodesByGroups.sortNodesByGroups(groupedNodes, options, {
251
+ getGroupCompareOptions: groupNumber =>
252
+ getCustomGroupsCompareOptions.getCustomGroupsCompareOptions(
253
+ options,
254
+ groupNumber,
255
+ ),
170
256
  ignoreEslintDisabledNodes,
171
257
  }),
172
258
  )
173
259
  let sortedNodes = sortNodesIgnoringEslintDisabledNodes(false)
174
260
  let sortedNodesExcludingEslintDisabled =
175
261
  sortNodesIgnoringEslintDisabledNodes(true)
262
+ let nodeIndexMap = createNodeIndexMap.createNodeIndexMap(sortedNodes)
176
263
  pairwise.pairwise(nodes, (left, right) => {
177
- let indexOfLeft = sortedNodes.indexOf(left)
178
- let indexOfRight = sortedNodes.indexOf(right)
264
+ let leftIndex = nodeIndexMap.get(left)
265
+ let rightIndex = nodeIndexMap.get(right)
266
+ let leftNumber = getGroupNumber.getGroupNumber(options.groups, left)
267
+ let rightNumber = getGroupNumber.getGroupNumber(options.groups, right)
179
268
  let indexOfRightExcludingEslintDisabled =
180
269
  sortedNodesExcludingEslintDisabled.indexOf(right)
181
270
  if (
182
- indexOfLeft < indexOfRight &&
183
- indexOfLeft < indexOfRightExcludingEslintDisabled
271
+ leftIndex < rightIndex &&
272
+ leftIndex < indexOfRightExcludingEslintDisabled
184
273
  ) {
185
274
  return
186
275
  }
@@ -196,13 +285,20 @@ let sortArray = (context, messageId, elements) => {
196
285
  data: {
197
286
  right: toSingleLine.toSingleLine(right.name),
198
287
  left: toSingleLine.toSingleLine(left.name),
288
+ rightGroup: right.group,
289
+ leftGroup: left.group,
199
290
  },
291
+ messageId:
292
+ leftNumber === rightNumber
293
+ ? availableMessageIds.unexpectedOrder
294
+ : availableMessageIds.unexpectedGroupOrder,
200
295
  node: right.node,
201
- messageId,
202
296
  })
203
297
  })
204
298
  }
205
299
  }
300
+ let getNodeName = ({ sourceCode, element }) =>
301
+ element.type === 'Literal' ? `${element.value}` : sourceCode.getText(element)
206
302
  exports.default = sortArrayIncludes
207
303
  exports.defaultOptions = defaultOptions
208
304
  exports.jsonSchema = jsonSchema
@@ -0,0 +1,10 @@
1
+ 'use strict'
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' })
3
+ const commonJsonSchemas = require('../utils/common-json-schemas.js')
4
+ let allSelectors = ['literal', 'spread']
5
+ let singleCustomGroupJsonSchema = {
6
+ selector: commonJsonSchemas.buildCustomGroupSelectorJsonSchema(allSelectors),
7
+ elementNamePattern: commonJsonSchemas.elementNamePatternJsonSchema,
8
+ }
9
+ exports.allSelectors = allSelectors
10
+ exports.singleCustomGroupJsonSchema = singleCustomGroupJsonSchema
@@ -2,10 +2,11 @@
2
2
  const commonJsonSchemas = require('../utils/common-json-schemas.js')
3
3
  const sortNodesByDependencies = require('../utils/sort-nodes-by-dependencies.js')
4
4
  const validateNewlinesAndPartitionConfiguration = require('../utils/validate-newlines-and-partition-configuration.js')
5
+ const validateGeneratedGroupsConfiguration = require('../utils/validate-generated-groups-configuration.js')
5
6
  const sortClasses_types = require('./sort-classes.types.js')
6
- const validateGeneratedGroupsConfiguration = require('./validate-generated-groups-configuration.js')
7
+ const validateCustomSortConfiguration = require('../utils/validate-custom-sort-configuration.js')
7
8
  const sortClassesUtils = require('./sort-classes-utils.js')
8
- const getCustomGroupsCompareOptions = require('./get-custom-groups-compare-options.js')
9
+ const getCustomGroupsCompareOptions = require('../utils/get-custom-groups-compare-options.js')
9
10
  const generatePredefinedGroups = require('../utils/generate-predefined-groups.js')
10
11
  const getEslintDisabledLines = require('../utils/get-eslint-disabled-lines.js')
11
12
  const isNodeEslintDisabled = require('../utils/is-node-eslint-disabled.js')
@@ -62,6 +63,7 @@ let defaultOptions = {
62
63
  ignoreCase: true,
63
64
  customGroups: [],
64
65
  locales: 'en-US',
66
+ alphabet: '',
65
67
  order: 'asc',
66
68
  }
67
69
  const sortClasses = createEslintRule.createEslintRule({
@@ -77,6 +79,7 @@ const sortClasses = createEslintRule.createEslintRule({
77
79
  settings,
78
80
  defaultOptions,
79
81
  )
82
+ validateCustomSortConfiguration.validateCustomSortConfiguration(options)
80
83
  validateGeneratedGroupsConfiguration.validateGeneratedGroupsConfiguration(
81
84
  {
82
85
  customGroups: options.customGroups,
@@ -391,14 +394,14 @@ const sortClasses = createEslintRule.createEslintRule({
391
394
  }
392
395
  selectors.push('property')
393
396
  }
394
- for (let officialGroup of generatePredefinedGroups.generatePredefinedGroups(
395
- {
397
+ let predefinedGroups =
398
+ generatePredefinedGroups.generatePredefinedGroups({
396
399
  cache: cachedGroupsByModifiersAndSelectors,
397
400
  selectors,
398
401
  modifiers,
399
- },
400
- )) {
401
- defineGroup(officialGroup)
402
+ })
403
+ for (let predefinedGroup of predefinedGroups) {
404
+ defineGroup(predefinedGroup)
402
405
  }
403
406
  for (let customGroup of options.customGroups) {
404
407
  if (
@@ -457,14 +460,13 @@ const sortClasses = createEslintRule.createEslintRule({
457
460
  lastMember,
458
461
  sortingNode,
459
462
  )) ||
460
- (options.partitionByComment &&
461
- isPartitionComment.hasPartitionComment(
462
- options.partitionByComment,
463
- getCommentsBefore.getCommentsBefore({
464
- node: member,
465
- sourceCode,
466
- }),
467
- ))
463
+ isPartitionComment.hasPartitionComment(
464
+ options.partitionByComment,
465
+ getCommentsBefore.getCommentsBefore({
466
+ node: member,
467
+ sourceCode,
468
+ }),
469
+ )
468
470
  ) {
469
471
  accumulator.push([])
470
472
  }
@@ -594,10 +596,11 @@ const sortClasses = createEslintRule.createEslintRule({
594
596
  specialCharacters: commonJsonSchemas.specialCharactersJsonSchema,
595
597
  newlinesBetween: commonJsonSchemas.newlinesBetweenJsonSchema,
596
598
  ignoreCase: commonJsonSchemas.ignoreCaseJsonSchema,
599
+ alphabet: commonJsonSchemas.alphabetJsonSchema,
600
+ type: commonJsonSchemas.buildTypeJsonSchema(),
597
601
  locales: commonJsonSchemas.localesJsonSchema,
598
602
  groups: commonJsonSchemas.groupsJsonSchema,
599
603
  order: commonJsonSchemas.orderJsonSchema,
600
- type: commonJsonSchemas.typeJsonSchema,
601
604
  },
602
605
  additionalProperties: false,
603
606
  type: 'object',