Skip to content

Commit

Permalink
feat: add partition by new line option to sort-objects rule
Browse files Browse the repository at this point in the history
  • Loading branch information
azat-io authored Nov 11, 2023
1 parent 4b81340 commit 8654e44
Show file tree
Hide file tree
Showing 5 changed files with 274 additions and 20 deletions.
13 changes: 10 additions & 3 deletions docs/rules/sort-objects.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,10 @@ interface Options {
order?: 'asc' | 'desc'
'ignore-case'?: boolean
groups?: (string | string[])[]
'custom-groups': { [key: string]: string[] | string }
'styled-components': boolean
'partition-by-comment': string[] | string | boolean
'custom-groups'?: { [key: string]: string[] | string }
'styled-components'?: boolean
'partition-by-comment'?: string[] | string | boolean
'partition-by-new-line'?: boolean
}
```

Expand Down Expand Up @@ -147,6 +148,12 @@ You can set comments that would separate the properties of objects into logical

The [minimatch](https://github.com/isaacs/minimatch) library is used for pattern matching.

### partition-by-new-line

<sub>(default: `false`)</sub>

When `true`, does not sort the object's keys if there is an empty string between them.

## ⚙️ Usage

::: code-group
Expand Down
18 changes: 4 additions & 14 deletions rules/sort-imports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import type { SortingNode } from '../typings'

import { getCommentBefore } from '../utils/get-comment-before'
import { createEslintRule } from '../utils/create-eslint-rule'
import { getLinesBetween } from '../utils/get-lines-between'
import { getGroupNumber } from '../utils/get-group-number'
import { getNodeRange } from '../utils/get-node-range'
import { rangeToDiff } from '../utils/range-to-diff'
Expand Down Expand Up @@ -393,18 +394,6 @@ export default createEslintRule<Options<string[]>, MESSAGE_ID>({
},
).length

let getLinesBetweenImports = (
left: SortingNode,
right: SortingNode,
) => {
let linesBetweenImports = source.lines.slice(
left.node.loc.end.line,
right.node.loc.start.line - 1,
)

return linesBetweenImports.filter(line => !line.trim().length).length
}

let fix = (
fixer: TSESLint.RuleFixer,
nodesToFix: SortingNode[],
Expand Down Expand Up @@ -452,7 +441,8 @@ export default createEslintRule<Options<string[]>, MESSAGE_ID>({
let nextNode = formatted.at(i + 1)

if (nextNode) {
let linesBetweenImports = getLinesBetweenImports(
let linesBetweenImports = getLinesBetween(
source,
nodesToFix.at(i)!,
nodesToFix.at(i + 1)!,
)
Expand Down Expand Up @@ -530,7 +520,7 @@ export default createEslintRule<Options<string[]>, MESSAGE_ID>({
let leftNum = getGroupNumber(options.groups, left)
let rightNum = getGroupNumber(options.groups, right)

let numberOfEmptyLinesBetween = getLinesBetweenImports(left, right)
let numberOfEmptyLinesBetween = getLinesBetween(source, left, right)

if (
!(
Expand Down
26 changes: 23 additions & 3 deletions rules/sort-objects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import type { PartitionComment, SortingNode } from '../typings'
import { isPartitionComment } from '../utils/is-partition-comment'
import { getCommentBefore } from '../utils/get-comment-before'
import { createEslintRule } from '../utils/create-eslint-rule'
import { getLinesBetween } from '../utils/get-lines-between'
import { getGroupNumber } from '../utils/get-group-number'
import { toSingleLine } from '../utils/to-single-line'
import { rangeToDiff } from '../utils/range-to-diff'
Expand Down Expand Up @@ -33,6 +34,7 @@ type Options = [
Partial<{
'custom-groups': { [key: string]: string[] | string }
'partition-by-comment': PartitionComment
'partition-by-new-line': boolean
groups: (string[] | string)[]
'styled-components': boolean
'ignore-case': boolean
Expand Down Expand Up @@ -62,6 +64,10 @@ export default createEslintRule<Options, MESSAGE_ID>({
type: ['boolean', 'string', 'array'],
default: false,
},
'partition-by-new-line': {
type: 'boolean',
default: false,
},
'styled-components': {
type: 'boolean',
default: true,
Expand Down Expand Up @@ -107,6 +113,7 @@ export default createEslintRule<Options, MESSAGE_ID>({
) => {
if (node.properties.length > 1) {
let options = complete(context.options.at(0), {
'partition-by-new-line': false,
'partition-by-comment': false,
type: SortType.alphabetical,
'styled-components': true,
Expand Down Expand Up @@ -158,6 +165,7 @@ export default createEslintRule<Options, MESSAGE_ID>({
}

let comment = getCommentBefore(prop, source)
let lastProp = accumulator.at(-1)?.at(-1)

if (
options['partition-by-comment'] &&
Expand All @@ -184,6 +192,20 @@ export default createEslintRule<Options, MESSAGE_ID>({
name = source.text.slice(...prop.key.range)
}

let propSortingNode = {
size: rangeToDiff(prop.range),
node: prop,
name,
}

if (
options['partition-by-new-line'] &&
lastProp &&
getLinesBetween(source, lastProp, propSortingNode)
) {
accumulator.push([])
}

if (prop.value.type === 'AssignmentPattern') {
let addDependencies = (value: TSESTree.AssignmentPattern) => {
if (value.right.type === 'Identifier') {
Expand Down Expand Up @@ -252,12 +274,10 @@ export default createEslintRule<Options, MESSAGE_ID>({
setCustomGroups(options['custom-groups'], name)

let value = {
size: rangeToDiff(prop.range),
...propSortingNode,
group: getGroup(),
dependencies,
node: prop,
position,
name,
}

accumulator.at(-1)!.push(value)
Expand Down
221 changes: 221 additions & 0 deletions test/sort-objects.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -891,6 +891,82 @@ describe(RULE_NAME, () => {
],
},
)

ruleTester.run(
`${RULE_NAME}(${type}): allows to use new line as partition`,
rule,
{
valid: [
{
code: dedent`
let terrorist = {
name: 'Twelve',
nickname: 'Sphinx #2',
status: Status.Deceased,
height: '167 cm',
weight: '55 kg',
}
`,
options: [
{
...options,
'partition-by-new-line': true,
},
],
},
],
invalid: [
{
code: dedent`
let terrorist = {
nickname: 'Sphinx #2',
name: 'Twelve',
status: Status.Deceased,
weight: '55 kg',
height: '167 cm',
}
`,
output: dedent`
let terrorist = {
name: 'Twelve',
nickname: 'Sphinx #2',
status: Status.Deceased,
height: '167 cm',
weight: '55 kg',
}
`,
options: [
{
...options,
'partition-by-new-line': true,
},
],
errors: [
{
messageId: 'unexpectedObjectsOrder',
data: {
left: 'nickname',
right: 'name',
},
},
{
messageId: 'unexpectedObjectsOrder',
data: {
left: 'weight',
right: 'height',
},
},
],
},
],
},
)
})

describe(`${RULE_NAME}: sorting by natural order`, () => {
Expand Down Expand Up @@ -1582,6 +1658,82 @@ describe(RULE_NAME, () => {
],
},
)

ruleTester.run(
`${RULE_NAME}(${type}): allows to use new line as partition`,
rule,
{
valid: [
{
code: dedent`
let terrorist = {
name: 'Twelve',
nickname: 'Sphinx #2',
status: Status.Deceased,
height: '167 cm',
weight: '55 kg',
}
`,
options: [
{
...options,
'partition-by-new-line': true,
},
],
},
],
invalid: [
{
code: dedent`
let terrorist = {
nickname: 'Sphinx #2',
name: 'Twelve',
status: Status.Deceased,
weight: '55 kg',
height: '167 cm',
}
`,
output: dedent`
let terrorist = {
name: 'Twelve',
nickname: 'Sphinx #2',
status: Status.Deceased,
height: '167 cm',
weight: '55 kg',
}
`,
options: [
{
...options,
'partition-by-new-line': true,
},
],
errors: [
{
messageId: 'unexpectedObjectsOrder',
data: {
left: 'nickname',
right: 'name',
},
},
{
messageId: 'unexpectedObjectsOrder',
data: {
left: 'weight',
right: 'height',
},
},
],
},
],
},
)
})

describe(`${RULE_NAME}: sorting by line length`, () => {
Expand Down Expand Up @@ -2321,6 +2473,75 @@ describe(RULE_NAME, () => {
],
},
)

ruleTester.run(
`${RULE_NAME}(${type}): allows to use new line as partition`,
rule,
{
valid: [
{
code: dedent`
let terrorist = {
nickname: 'Sphinx #2',
name: 'Twelve',
status: Status.Deceased,
height: '167 cm',
weight: '55 kg',
}
`,
options: [
{
...options,
'partition-by-new-line': true,
},
],
},
],
invalid: [
{
code: dedent`
let terrorist = {
nickname: 'Sphinx #2',
name: 'Twelve',
status: Status.Deceased,
weight: '55 kg',
height: '167 cm',
}
`,
output: dedent`
let terrorist = {
nickname: 'Sphinx #2',
name: 'Twelve',
status: Status.Deceased,
height: '167 cm',
weight: '55 kg',
}
`,
options: [
{
...options,
'partition-by-new-line': true,
},
],
errors: [
{
messageId: 'unexpectedObjectsOrder',
data: {
left: 'weight',
right: 'height',
},
},
],
},
],
},
)
})

describe(`${RULE_NAME}: misc`, () => {
Expand Down
Loading

0 comments on commit 8654e44

Please sign in to comment.