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.
Files changed (34) 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.js +2 -0
  5. package/dist/rules/sort-classes.js +6 -2
  6. package/dist/rules/sort-decorators.js +4 -0
  7. package/dist/rules/sort-enums.js +5 -0
  8. package/dist/rules/sort-exports.js +4 -0
  9. package/dist/rules/sort-heritage-clauses.js +4 -0
  10. package/dist/rules/sort-imports.js +5 -0
  11. package/dist/rules/sort-interfaces.js +1 -0
  12. package/dist/rules/sort-intersection-types.js +4 -0
  13. package/dist/rules/sort-jsx-props.js +4 -0
  14. package/dist/rules/sort-maps.js +4 -0
  15. package/dist/rules/sort-modules.js +6 -2
  16. package/dist/rules/sort-named-exports.js +4 -0
  17. package/dist/rules/sort-named-imports.js +4 -0
  18. package/dist/rules/sort-object-types.js +10 -11
  19. package/dist/rules/sort-objects.js +32 -5
  20. package/dist/rules/sort-switch-case.js +4 -0
  21. package/dist/rules/sort-union-types.js +4 -0
  22. package/dist/rules/sort-variable-declarations.js +4 -0
  23. package/dist/utils/alphabet.js +385 -0
  24. package/dist/utils/common-json-schemas.js +16 -1
  25. package/dist/utils/compare.js +88 -38
  26. package/dist/utils/convert-boolean-to-sign.js +4 -0
  27. package/dist/{rules → utils}/get-custom-groups-compare-options.js +1 -0
  28. package/dist/utils/get-matching-context-options.js +18 -0
  29. package/dist/utils/get-settings.js +1 -0
  30. package/dist/utils/is-node-function-type.js +15 -0
  31. package/dist/utils/validate-custom-sort-configuration.js +11 -0
  32. package/dist/{rules → utils}/validate-generated-groups-configuration.js +1 -1
  33. package/package.json +7 -3
  34. package/readme.md +4 -3
@@ -5,13 +5,15 @@ Object.defineProperties(exports, {
5
5
  })
6
6
  const commonJsonSchemas = require('../utils/common-json-schemas.js')
7
7
  const validateNewlinesAndPartitionConfiguration = require('../utils/validate-newlines-and-partition-configuration.js')
8
- const validateGeneratedGroupsConfiguration = require('./validate-generated-groups-configuration.js')
9
- const getCustomGroupsCompareOptions = require('./get-custom-groups-compare-options.js')
8
+ const validateGeneratedGroupsConfiguration = require('../utils/validate-generated-groups-configuration.js')
9
+ const validateCustomSortConfiguration = require('../utils/validate-custom-sort-configuration.js')
10
+ const getCustomGroupsCompareOptions = require('../utils/get-custom-groups-compare-options.js')
10
11
  const generatePredefinedGroups = require('../utils/generate-predefined-groups.js')
11
12
  const getEslintDisabledLines = require('../utils/get-eslint-disabled-lines.js')
12
13
  const sortObjectTypes_types = require('./sort-object-types.types.js')
13
14
  const isNodeEslintDisabled = require('../utils/is-node-eslint-disabled.js')
14
15
  const isPartitionComment = require('../utils/is-partition-comment.js')
16
+ const isNodeFunctionType = require('../utils/is-node-function-type.js')
15
17
  const sortNodesByGroups = require('../utils/sort-nodes-by-groups.js')
16
18
  const getCommentsBefore = require('../utils/get-comments-before.js')
17
19
  const makeNewlinesFixes = require('../utils/make-newlines-fixes.js')
@@ -43,6 +45,7 @@ let defaultOptions = {
43
45
  ignoreCase: true,
44
46
  customGroups: {},
45
47
  locales: 'en-US',
48
+ alphabet: '',
46
49
  order: 'asc',
47
50
  groups: [],
48
51
  }
@@ -79,6 +82,7 @@ let jsonSchema = {
79
82
  specialCharacters: commonJsonSchemas.specialCharactersJsonSchema,
80
83
  newlinesBetween: commonJsonSchemas.newlinesBetweenJsonSchema,
81
84
  ignoreCase: commonJsonSchemas.ignoreCaseJsonSchema,
85
+ alphabet: commonJsonSchemas.alphabetJsonSchema,
82
86
  locales: commonJsonSchemas.localesJsonSchema,
83
87
  groups: commonJsonSchemas.groupsJsonSchema,
84
88
  order: commonJsonSchemas.orderJsonSchema,
@@ -143,6 +147,7 @@ let sortObjectTypeElements = ({
143
147
  settings,
144
148
  defaultOptions,
145
149
  )
150
+ validateCustomSortConfiguration.validateCustomSortConfiguration(options)
146
151
  validateGeneratedGroupsConfiguration.validateGeneratedGroupsConfiguration({
147
152
  customGroups: options.customGroups,
148
153
  selectors: sortObjectTypes_types.allSelectors,
@@ -166,7 +171,7 @@ let sortObjectTypeElements = ({
166
171
  })
167
172
  let formattedMembers = elements.reduce(
168
173
  (accumulator, typeElement) => {
169
- var _a, _b, _c, _d, _e
174
+ var _a, _b, _c, _d
170
175
  if (typeElement.type === 'TSCallSignatureDeclaration') {
171
176
  accumulator.push([])
172
177
  return accumulator
@@ -216,13 +221,7 @@ let sortObjectTypeElements = ({
216
221
  if (typeElement.type === 'TSIndexSignature') {
217
222
  selectors.push('index-signature')
218
223
  }
219
- if (
220
- typeElement.type === 'TSMethodSignature' ||
221
- (typeElement.type === 'TSPropertySignature' &&
222
- ((_d = typeElement.typeAnnotation) == null
223
- ? void 0
224
- : _d.typeAnnotation.type) === 'TSFunctionType')
225
- ) {
224
+ if (isNodeFunctionType.isNodeFunctionType(typeElement)) {
226
225
  selectors.push('method')
227
226
  }
228
227
  if (typeElement.loc.start.line !== typeElement.loc.end.line) {
@@ -304,7 +303,7 @@ let sortObjectTypeElements = ({
304
303
  ) {
305
304
  accumulator.push([])
306
305
  }
307
- ;(_e = accumulator.at(-1)) == null ? void 0 : _e.push(sortingNode)
306
+ ;(_d = accumulator.at(-1)) == null ? void 0 : _d.push(sortingNode)
308
307
  return accumulator
309
308
  },
310
309
  [[]],
@@ -2,7 +2,9 @@
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 validateCustomSortConfiguration = require('../utils/validate-custom-sort-configuration.js')
5
6
  const validateGroupsConfiguration = require('../utils/validate-groups-configuration.js')
7
+ const getMatchingContextOptions = require('../utils/get-matching-context-options.js')
6
8
  const getEslintDisabledLines = require('../utils/get-eslint-disabled-lines.js')
7
9
  const isNodeEslintDisabled = require('../utils/is-node-eslint-disabled.js')
8
10
  const isPartitionComment = require('../utils/is-partition-comment.js')
@@ -33,11 +35,13 @@ let defaultOptions = {
33
35
  objectDeclarations: true,
34
36
  styledComponents: true,
35
37
  destructureOnly: false,
38
+ useConfigurationIf: {},
36
39
  type: 'alphabetical',
37
40
  ignorePattern: [],
38
41
  ignoreCase: true,
39
42
  customGroups: {},
40
43
  locales: 'en-US',
44
+ alphabet: '',
41
45
  order: 'asc',
42
46
  groups: [],
43
47
  }
@@ -48,11 +52,20 @@ const sortObjects = createEslintRule.createEslintRule({
48
52
  return
49
53
  }
50
54
  let settings = getSettings.getSettings(context.settings)
55
+ let sourceCode = getSourceCode.getSourceCode(context)
56
+ let matchedContextOptions =
57
+ getMatchingContextOptions.getMatchingContextOptions({
58
+ nodeNames: nodeObject.properties
59
+ .map(property => getNodeName({ sourceCode, property }))
60
+ .filter(nodeName => nodeName !== null),
61
+ contextOptions: context.options,
62
+ })
51
63
  let options = complete.complete(
52
- context.options.at(0),
64
+ matchedContextOptions,
53
65
  settings,
54
66
  defaultOptions,
55
67
  )
68
+ validateCustomSortConfiguration.validateCustomSortConfiguration(options)
56
69
  validateGroupsConfiguration.validateGroupsConfiguration(
57
70
  options.groups,
58
71
  ['multiline', 'method', 'unknown'],
@@ -130,7 +143,6 @@ const sortObjects = createEslintRule.createEslintRule({
130
143
  ) {
131
144
  return
132
145
  }
133
- let sourceCode = getSourceCode.getSourceCode(context)
134
146
  let eslintDisabledLines = getEslintDisabledLines.getEslintDisabledLines({
135
147
  ruleName: context.id,
136
148
  sourceCode,
@@ -382,8 +394,8 @@ const sortObjects = createEslintRule.createEslintRule({
382
394
  }
383
395
  },
384
396
  meta: {
385
- schema: [
386
- {
397
+ schema: {
398
+ items: {
387
399
  properties: {
388
400
  destructuredObjects: {
389
401
  oneOf: [
@@ -430,10 +442,12 @@ const sortObjects = createEslintRule.createEslintRule({
430
442
  type: 'boolean',
431
443
  },
432
444
  partitionByNewLine: commonJsonSchemas.partitionByNewLineJsonSchema,
445
+ useConfigurationIf: commonJsonSchemas.useConfigurationIfJsonSchema,
433
446
  specialCharacters: commonJsonSchemas.specialCharactersJsonSchema,
434
447
  newlinesBetween: commonJsonSchemas.newlinesBetweenJsonSchema,
435
448
  customGroups: commonJsonSchemas.customGroupsJsonSchema,
436
449
  ignoreCase: commonJsonSchemas.ignoreCaseJsonSchema,
450
+ alphabet: commonJsonSchemas.alphabetJsonSchema,
437
451
  locales: commonJsonSchemas.localesJsonSchema,
438
452
  groups: commonJsonSchemas.groupsJsonSchema,
439
453
  order: commonJsonSchemas.orderJsonSchema,
@@ -442,7 +456,9 @@ const sortObjects = createEslintRule.createEslintRule({
442
456
  additionalProperties: false,
443
457
  type: 'object',
444
458
  },
445
- ],
459
+ uniqueItems: true,
460
+ type: 'array',
461
+ },
446
462
  messages: {
447
463
  unexpectedObjectsGroupOrder:
448
464
  'Expected "{{right}}" ({{rightGroup}}) to come before "{{left}}" ({{leftGroup}}).',
@@ -465,4 +481,15 @@ const sortObjects = createEslintRule.createEslintRule({
465
481
  defaultOptions: [defaultOptions],
466
482
  name: 'sort-objects',
467
483
  })
484
+ let getNodeName = ({ sourceCode, property }) => {
485
+ if (property.type === 'SpreadElement' || property.type === 'RestElement') {
486
+ return null
487
+ }
488
+ if (property.key.type === 'Identifier') {
489
+ return property.key.name
490
+ } else if (property.key.type === 'Literal') {
491
+ return `${property.key.value}`
492
+ }
493
+ return sourceCode.getText(property.key)
494
+ }
468
495
  module.exports = sortObjects
@@ -1,5 +1,6 @@
1
1
  'use strict'
2
2
  const commonJsonSchemas = require('../utils/common-json-schemas.js')
3
+ const validateCustomSortConfiguration = require('../utils/validate-custom-sort-configuration.js')
3
4
  const makeCommentAfterFixes = require('../utils/make-comment-after-fixes.js')
4
5
  const createEslintRule = require('../utils/create-eslint-rule.js')
5
6
  const getSourceCode = require('../utils/get-source-code.js')
@@ -16,6 +17,7 @@ let defaultOptions = {
16
17
  type: 'alphabetical',
17
18
  ignoreCase: true,
18
19
  locales: 'en-US',
20
+ alphabet: '',
19
21
  order: 'asc',
20
22
  }
21
23
  const sortSwitchCase = createEslintRule.createEslintRule({
@@ -30,6 +32,7 @@ const sortSwitchCase = createEslintRule.createEslintRule({
30
32
  settings,
31
33
  defaultOptions,
32
34
  )
35
+ validateCustomSortConfiguration.validateCustomSortConfiguration(options)
33
36
  let sourceCode = getSourceCode.getSourceCode(context)
34
37
  let isDiscriminantTrue =
35
38
  switchNode.discriminant.type === 'Literal' &&
@@ -218,6 +221,7 @@ const sortSwitchCase = createEslintRule.createEslintRule({
218
221
  properties: {
219
222
  specialCharacters: commonJsonSchemas.specialCharactersJsonSchema,
220
223
  ignoreCase: commonJsonSchemas.ignoreCaseJsonSchema,
224
+ alphabet: commonJsonSchemas.alphabetJsonSchema,
221
225
  locales: commonJsonSchemas.localesJsonSchema,
222
226
  order: commonJsonSchemas.orderJsonSchema,
223
227
  type: commonJsonSchemas.typeJsonSchema,
@@ -1,6 +1,7 @@
1
1
  'use strict'
2
2
  const commonJsonSchemas = require('../utils/common-json-schemas.js')
3
3
  const validateNewlinesAndPartitionConfiguration = require('../utils/validate-newlines-and-partition-configuration.js')
4
+ const validateCustomSortConfiguration = require('../utils/validate-custom-sort-configuration.js')
4
5
  const validateGroupsConfiguration = require('../utils/validate-groups-configuration.js')
5
6
  const getEslintDisabledLines = require('../utils/get-eslint-disabled-lines.js')
6
7
  const isNodeEslintDisabled = require('../utils/is-node-eslint-disabled.js')
@@ -28,6 +29,7 @@ let defaultOptions = {
28
29
  type: 'alphabetical',
29
30
  ignoreCase: true,
30
31
  locales: 'en-US',
32
+ alphabet: '',
31
33
  order: 'asc',
32
34
  groups: [],
33
35
  }
@@ -40,6 +42,7 @@ const sortUnionTypes = createEslintRule.createEslintRule({
40
42
  settings,
41
43
  defaultOptions,
42
44
  )
45
+ validateCustomSortConfiguration.validateCustomSortConfiguration(options)
43
46
  validateGroupsConfiguration.validateGroupsConfiguration(
44
47
  options.groups,
45
48
  [
@@ -249,6 +252,7 @@ const sortUnionTypes = createEslintRule.createEslintRule({
249
252
  specialCharacters: commonJsonSchemas.specialCharactersJsonSchema,
250
253
  newlinesBetween: commonJsonSchemas.newlinesBetweenJsonSchema,
251
254
  ignoreCase: commonJsonSchemas.ignoreCaseJsonSchema,
255
+ alphabet: commonJsonSchemas.alphabetJsonSchema,
252
256
  locales: commonJsonSchemas.localesJsonSchema,
253
257
  groups: commonJsonSchemas.groupsJsonSchema,
254
258
  order: commonJsonSchemas.orderJsonSchema,
@@ -1,6 +1,7 @@
1
1
  'use strict'
2
2
  const commonJsonSchemas = require('../utils/common-json-schemas.js')
3
3
  const sortNodesByDependencies = require('../utils/sort-nodes-by-dependencies.js')
4
+ const validateCustomSortConfiguration = require('../utils/validate-custom-sort-configuration.js')
4
5
  const getEslintDisabledLines = require('../utils/get-eslint-disabled-lines.js')
5
6
  const isNodeEslintDisabled = require('../utils/is-node-eslint-disabled.js')
6
7
  const isPartitionComment = require('../utils/is-partition-comment.js')
@@ -23,6 +24,7 @@ let defaultOptions = {
23
24
  type: 'alphabetical',
24
25
  ignoreCase: true,
25
26
  locales: 'en-US',
27
+ alphabet: '',
26
28
  order: 'asc',
27
29
  }
28
30
  const sortVariableDeclarations = createEslintRule.createEslintRule({
@@ -37,6 +39,7 @@ const sortVariableDeclarations = createEslintRule.createEslintRule({
37
39
  settings,
38
40
  defaultOptions,
39
41
  )
42
+ validateCustomSortConfiguration.validateCustomSortConfiguration(options)
40
43
  let sourceCode = getSourceCode.getSourceCode(context)
41
44
  let eslintDisabledLines = getEslintDisabledLines.getEslintDisabledLines({
42
45
  ruleName: context.id,
@@ -231,6 +234,7 @@ const sortVariableDeclarations = createEslintRule.createEslintRule({
231
234
  partitionByNewLine: commonJsonSchemas.partitionByNewLineJsonSchema,
232
235
  specialCharacters: commonJsonSchemas.specialCharactersJsonSchema,
233
236
  ignoreCase: commonJsonSchemas.ignoreCaseJsonSchema,
237
+ alphabet: commonJsonSchemas.alphabetJsonSchema,
234
238
  locales: commonJsonSchemas.localesJsonSchema,
235
239
  order: commonJsonSchemas.orderJsonSchema,
236
240
  type: commonJsonSchemas.typeJsonSchema,
@@ -0,0 +1,385 @@
1
+ 'use strict'
2
+ var __defProp = Object.defineProperty
3
+ var __defNormalProp = (obj, key, value) =>
4
+ key in obj
5
+ ? __defProp(obj, key, {
6
+ enumerable: true,
7
+ configurable: true,
8
+ writable: true,
9
+ value,
10
+ })
11
+ : (obj[key] = value)
12
+ var __publicField = (obj, key, value) =>
13
+ __defNormalProp(obj, typeof key !== 'symbol' ? key + '' : key, value)
14
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' })
15
+ const naturalOrderby = require('natural-orderby')
16
+ const convertBooleanToSign = require('./convert-boolean-to-sign.js')
17
+ class Alphabet {
18
+ constructor(characters) {
19
+ __publicField(this, '_characters', [])
20
+ this._characters = characters
21
+ }
22
+ /**
23
+ * Generates an alphabet from the given characters.
24
+ * @param {string|string[]} values - The characters to generate the alphabet from
25
+ * @returns {Alphabet} - The wrapped alphabet
26
+ */
27
+ static generateFrom(values) {
28
+ let arrayValues = typeof values === 'string' ? [...values] : values
29
+ if (arrayValues.length !== new Set(arrayValues).size) {
30
+ throw new Error('The alphabet must not contain repeated characters')
31
+ }
32
+ if (arrayValues.some(value => value.length !== 1)) {
33
+ throw new Error('The alphabet must contain single characters')
34
+ }
35
+ return new Alphabet(
36
+ arrayValues.map(value =>
37
+ Alphabet._convertCodepointToCharacter(value.codePointAt(0)),
38
+ ),
39
+ )
40
+ }
41
+ /**
42
+ * Generates an alphabet containing relevant characters from the Unicode
43
+ * standard. Contains the Unicode planes 0 and 1.
44
+ * @returns {Alphabet} - The generated alphabet
45
+ */
46
+ static generateRecommendedAlphabet() {
47
+ return Alphabet._generateAlphabetToRange(131071 + 1)
48
+ }
49
+ /**
50
+ * Generates an alphabet containing all characters from the Unicode standard
51
+ * except for irrelevant Unicode planes.
52
+ * Contains the Unicode planes 0, 1, 2 and 3.
53
+ * @returns {Alphabet} - The generated alphabet
54
+ */
55
+ static generateCompleteAlphabet() {
56
+ return Alphabet._generateAlphabetToRange(262143 + 1)
57
+ }
58
+ static _convertCodepointToCharacter(codePoint) {
59
+ let character = String.fromCodePoint(codePoint)
60
+ let lowercaseCharacter = character.toLowerCase()
61
+ let uppercaseCharacter = character.toUpperCase()
62
+ return {
63
+ value: character,
64
+ codePoint,
65
+ ...(lowercaseCharacter === character
66
+ ? null
67
+ : {
68
+ lowercaseCharacterCodePoint: lowercaseCharacter.codePointAt(0),
69
+ }),
70
+ ...(uppercaseCharacter === character
71
+ ? null
72
+ : {
73
+ uppercaseCharacterCodePoint: uppercaseCharacter.codePointAt(0),
74
+ }),
75
+ }
76
+ }
77
+ /**
78
+ * Generates an alphabet containing relevant characters from the Unicode
79
+ * standard.
80
+ * @param {number} maxCodePoint - The maximum code point to generate the
81
+ * alphabet to
82
+ * @returns {Alphabet} - The generated alphabet
83
+ */
84
+ static _generateAlphabetToRange(maxCodePoint) {
85
+ let totalCharacters = Array.from({ length: maxCodePoint }, (_, i) =>
86
+ Alphabet._convertCodepointToCharacter(i),
87
+ )
88
+ return new Alphabet(totalCharacters)
89
+ }
90
+ /**
91
+ * For each character with a lower and upper case, permutes the two cases
92
+ * so that the alphabet is ordered by the case priority entered.
93
+ * @param {string} casePriority - The case to prioritize
94
+ * @returns {Alphabet} - The same alphabet instance with the cases prioritized
95
+ * @example
96
+ * Alphabet.generateFrom('aAbBcdCD')
97
+ * .prioritizeCase('uppercase')
98
+ * // Returns 'AaBbCDcd'
99
+ */
100
+ prioritizeCase(casePriority) {
101
+ let charactersWithCase = this._getCharactersWithCase()
102
+ let parsedIndexes = /* @__PURE__ */ new Set()
103
+ let indexByCodePoints = this._characters.reduce(
104
+ (indexByCodePoint, character, index) => {
105
+ indexByCodePoint[character.codePoint] = index
106
+ return indexByCodePoint
107
+ },
108
+ {},
109
+ )
110
+ for (let { character, index } of charactersWithCase) {
111
+ if (parsedIndexes.has(index)) {
112
+ continue
113
+ }
114
+ parsedIndexes.add(index)
115
+ let otherCharacterIndex =
116
+ indexByCodePoints[
117
+ character.uppercaseCharacterCodePoint ??
118
+ character.lowercaseCharacterCodePoint
119
+ ]
120
+ if (otherCharacterIndex === void 0) {
121
+ continue
122
+ }
123
+ parsedIndexes.add(otherCharacterIndex)
124
+ let isCharacterUppercase = !character.uppercaseCharacterCodePoint
125
+ if (isCharacterUppercase) {
126
+ if (
127
+ (casePriority === 'uppercase' && index < otherCharacterIndex) ||
128
+ (casePriority === 'lowercase' && index > otherCharacterIndex)
129
+ ) {
130
+ continue
131
+ }
132
+ } else {
133
+ if (
134
+ (casePriority === 'uppercase' && index > otherCharacterIndex) ||
135
+ (casePriority === 'lowercase' && index < otherCharacterIndex)
136
+ ) {
137
+ continue
138
+ }
139
+ }
140
+ this._characters[index] = this._characters[otherCharacterIndex]
141
+ this._characters[otherCharacterIndex] = character
142
+ }
143
+ return this
144
+ }
145
+ /**
146
+ * Adds specific characters to the end of the alphabet.
147
+ * @param {string|string[]} values - The characters to push to the alphabet
148
+ * @returns {Alphabet} - The same alphabet instance without the specified
149
+ * characters
150
+ * @example
151
+ * Alphabet.generateFrom('ab')
152
+ * .pushCharacters('cd')
153
+ * // Returns 'abcd'
154
+ */
155
+ pushCharacters(values) {
156
+ let arrayValues = typeof values === 'string' ? [...values] : values
157
+ let valuesSet = new Set(arrayValues)
158
+ let valuesAlreadyExisting = this._characters.filter(({ value }) =>
159
+ valuesSet.has(value),
160
+ )
161
+ if (valuesAlreadyExisting.length > 0) {
162
+ throw new Error(
163
+ `The alphabet already contains the characters ${valuesAlreadyExisting
164
+ .slice(0, 5)
165
+ .map(({ value }) => value)
166
+ .join(', ')}`,
167
+ )
168
+ }
169
+ if (arrayValues.some(value => value.length !== 1)) {
170
+ throw new Error('Only single characters may be pushed')
171
+ }
172
+ this._characters.push(
173
+ ...[...valuesSet].map(value =>
174
+ Alphabet._convertCodepointToCharacter(value.codePointAt(0)),
175
+ ),
176
+ )
177
+ return this
178
+ }
179
+ /**
180
+ * Permutes characters with cases so that all characters with the entered case
181
+ * are put before the other characters.
182
+ * @param {string} caseToComeFirst - The case to put before the other
183
+ * characters
184
+ * @returns {Alphabet} - The same alphabet instance with all characters with
185
+ * case before all the characters with the other case
186
+ */
187
+ placeAllWithCaseBeforeAllWithOtherCase(caseToComeFirst) {
188
+ let charactersWithCase = this._getCharactersWithCase()
189
+ let orderedCharacters = [
190
+ ...charactersWithCase.filter(character =>
191
+ caseToComeFirst === 'uppercase'
192
+ ? !character.character.uppercaseCharacterCodePoint
193
+ : character.character.uppercaseCharacterCodePoint,
194
+ ),
195
+ ...charactersWithCase.filter(character =>
196
+ caseToComeFirst === 'uppercase'
197
+ ? character.character.uppercaseCharacterCodePoint
198
+ : !character.character.uppercaseCharacterCodePoint,
199
+ ),
200
+ ]
201
+ for (let [i, element] of charactersWithCase.entries()) {
202
+ this._characters[element.index] = orderedCharacters[i].character
203
+ }
204
+ return this
205
+ }
206
+ /**
207
+ * Places a specific character right before another character in the alphabet.
208
+ * @param {object} params - The parameters for the operation
209
+ * @param {string} params.characterBefore - The character to come before
210
+ * characterAfter
211
+ * @param {string} params.characterAfter - The target character
212
+ * @returns {Alphabet} - The same alphabet instance with the specific
213
+ * character prioritized
214
+ * @example
215
+ * Alphabet.generateFrom('ab-cd/')
216
+ * .placeCharacterBefore({ characterBefore: '/', characterAfter: '-' })
217
+ * // Returns 'ab/-cd'
218
+ */
219
+ placeCharacterBefore({ characterBefore, characterAfter }) {
220
+ return this._placeCharacterBeforeOrAfter({
221
+ characterBefore,
222
+ characterAfter,
223
+ type: 'before',
224
+ })
225
+ }
226
+ /**
227
+ * Places a specific character right after another character in the alphabet.
228
+ * @param {object} params - The parameters for the operation
229
+ * @param {string} params.characterBefore - The target character
230
+ * @param {string} params.characterAfter - The character to come after
231
+ * characterBefore
232
+ * @returns {Alphabet} - The same alphabet instance with the specific
233
+ * character prioritized
234
+ * @example
235
+ * Alphabet.generateFrom('ab-cd/')
236
+ * .placeCharacterAfter({ characterBefore: '/', characterAfter: '-' })
237
+ * // Returns 'abcd/-'
238
+ */
239
+ placeCharacterAfter({ characterBefore, characterAfter }) {
240
+ return this._placeCharacterBeforeOrAfter({
241
+ characterBefore,
242
+ characterAfter,
243
+ type: 'after',
244
+ })
245
+ }
246
+ /**
247
+ * Removes specific characters from the alphabet by their range.
248
+ * @param {object} range - The Unicode range to remove characters from
249
+ * @param {number} range.start - The starting Unicode codepoint
250
+ * @param {number} range.end - The ending Unicode codepoint
251
+ * @returns {Alphabet} - The same alphabet instance without the characters
252
+ * from the specified range
253
+ */
254
+ removeUnicodeRange({ start, end }) {
255
+ this._characters = this._characters.filter(
256
+ ({ codePoint }) => codePoint < start || codePoint > end,
257
+ )
258
+ return this
259
+ }
260
+ /**
261
+ * Sorts the alphabet by the sorting function provided.
262
+ * @param {Function} sortingFunction - The sorting function to use
263
+ * @returns {Alphabet} - The same alphabet instance sorted by the sorting function provided
264
+ */
265
+ sortBy(sortingFunction) {
266
+ this._characters.sort((a, b) => sortingFunction(a.value, b.value))
267
+ return this
268
+ }
269
+ /**
270
+ * Removes specific characters from the alphabet.
271
+ * @param {string|string[]} values - The characters to remove from the
272
+ * alphabet
273
+ * @returns {Alphabet} - The same alphabet instance without the specified
274
+ * characters
275
+ * @example
276
+ * Alphabet.generateFrom('abcd')
277
+ * .removeCharacters('dcc')
278
+ * // Returns 'ab'
279
+ */
280
+ removeCharacters(values) {
281
+ this._characters = this._characters.filter(
282
+ ({ value }) => !values.includes(value),
283
+ )
284
+ return this
285
+ }
286
+ /**
287
+ * Sorts the alphabet by the natural order of the characters using
288
+ * `natural-orderby`.
289
+ * @param {string} locale - The locale to use for sorting
290
+ * @returns {Alphabet} - The same alphabet instance sorted by the natural
291
+ * order of the characters
292
+ */
293
+ sortByNaturalSort(locale) {
294
+ let naturalCompare = naturalOrderby.compare({
295
+ locale,
296
+ })
297
+ return this.sortBy((a, b) => naturalCompare(a, b))
298
+ }
299
+ /**
300
+ * Sorts the alphabet by the character code point.
301
+ * @returns {Alphabet} - The same alphabet instance sorted by the character
302
+ * code point
303
+ */
304
+ sortByCharCodeAt() {
305
+ return this.sortBy((a, b) =>
306
+ convertBooleanToSign.convertBooleanToSign(
307
+ a.charCodeAt(0) > b.charCodeAt(0),
308
+ ),
309
+ )
310
+ }
311
+ /**
312
+ * Sorts the alphabet by the locale order of the characters.
313
+ * @param {Intl.LocalesArgument} locales - The locales to use for sorting
314
+ * @returns {Alphabet} - The same alphabet instance sorted by the locale
315
+ * order of the characters
316
+ */
317
+ sortByLocaleCompare(locales) {
318
+ return this.sortBy((a, b) => a.localeCompare(b, locales))
319
+ }
320
+ /**
321
+ * Retrieves the characters from the alphabet.
322
+ * @returns {string} The characters from the alphabet
323
+ */
324
+ getCharacters() {
325
+ return this._characters.map(({ value }) => value).join('')
326
+ }
327
+ /**
328
+ * Reverses the alphabet.
329
+ * @returns {Alphabet} - The same alphabet instance reversed
330
+ * @example
331
+ * Alphabet.generateFrom('ab')
332
+ * .reverse()
333
+ * // Returns 'ba'
334
+ */
335
+ reverse() {
336
+ this._characters.reverse()
337
+ return this
338
+ }
339
+ _placeCharacterBeforeOrAfter({ characterBefore, characterAfter, type }) {
340
+ let indexOfCharacterAfter = this._characters.findIndex(
341
+ ({ value }) => value === characterAfter,
342
+ )
343
+ let indexOfCharacterBefore = this._characters.findIndex(
344
+ ({ value }) => value === characterBefore,
345
+ )
346
+ if (indexOfCharacterAfter === -1) {
347
+ throw new Error(`Character ${characterAfter} not found in alphabet`)
348
+ }
349
+ if (indexOfCharacterBefore === -1) {
350
+ throw new Error(`Character ${characterBefore} not found in alphabet`)
351
+ }
352
+ if (indexOfCharacterBefore <= indexOfCharacterAfter) {
353
+ return this
354
+ }
355
+ this._characters.splice(
356
+ type === 'before' ? indexOfCharacterAfter : indexOfCharacterBefore + 1,
357
+ 0,
358
+ this._characters[
359
+ type === 'before' ? indexOfCharacterBefore : indexOfCharacterAfter
360
+ ],
361
+ )
362
+ this._characters.splice(
363
+ type === 'before' ? indexOfCharacterBefore + 1 : indexOfCharacterAfter,
364
+ 1,
365
+ )
366
+ return this
367
+ }
368
+ _getCharactersWithCase() {
369
+ return this._characters
370
+ .map((character, index) => {
371
+ if (
372
+ !character.uppercaseCharacterCodePoint &&
373
+ !character.lowercaseCharacterCodePoint
374
+ ) {
375
+ return null
376
+ }
377
+ return {
378
+ character,
379
+ index,
380
+ }
381
+ })
382
+ .filter(element => element !== null)
383
+ }
384
+ }
385
+ exports.Alphabet = Alphabet