Skip to content

Commit

Permalink
feat: add custom ignore to enable customisable ignore sort-objects rule
Browse files Browse the repository at this point in the history
  • Loading branch information
KID-joker authored and azat-io committed Jul 22, 2024
1 parent 52a2258 commit 4fa2b3e
Show file tree
Hide file tree
Showing 3 changed files with 223 additions and 10 deletions.
36 changes: 28 additions & 8 deletions docs/content/rules/sort-objects.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -216,14 +216,6 @@ Example:

When `false`, this rule will be disabled for the styled-components like libraries.

### ignorePattern

<sub>(default: `[]`)</sub>

If you need to ignore a rule for some interfaces, you can specify their names or a pattern to ignore, for example: `'Component*'` to ignore all interfaces whose names begin with the word Component.

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

### partitionByComment

<sub>(default: `false`)</sub>
Expand All @@ -238,6 +230,34 @@ The [minimatch](https://github.com/isaacs/minimatch) library is used for pattern

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

### ignorePattern

<sub>(default: `[]`)</sub>

If you need to ignore a rule for some interfaces, you can specify their names or a pattern to ignore, for example: `'Component*'` to ignore all interfaces whose names begin with the word Component.

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

### customIgnore

<sub>(default: `[]`)</sub>

If you need to ignore certain objects using a more complex algorithm, you can write your own function.

This function takes two parameters as input: an object in the context of an abstract syntax tree and a filename. When writing this function I recommend you use [AST Explorer](https://astexplorer.net/), use TypeScript ESLint Parser. The function should return `true` if the object should be ignored.

For example, if you want to use this rule only when destructuring objects, you can use this function:

```js
{
customIgnore: [
(object, fileName) => {
return node.type !== 'ObjectPattern'
},
]
}
```

## Usage

<CodeTabs
Expand Down
18 changes: 17 additions & 1 deletion rules/sort-objects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ type SortingNodeWithPosition = {

type Options = [
Partial<{
customIgnore: ((
object: TSESTree.ObjectExpression | TSESTree.ObjectPattern,
filename: string,
) => boolean)[]
customGroups: { [key: string]: string[] | string }
type: 'alphabetical' | 'line-length' | 'natural'
partitionByComment: string[] | boolean | string
Expand Down Expand Up @@ -99,6 +103,9 @@ export default createEslintRule<Options, MESSAGE_ID>({
groups: {
type: 'array',
},
customIgnore: {
type: 'array',
},
},
additionalProperties: false,
},
Expand All @@ -125,12 +132,21 @@ export default createEslintRule<Options, MESSAGE_ID>({
ignorePattern: [],
ignoreCase: true,
customGroups: {},
customIgnore: [],
order: 'asc',
groups: [],
} as const)

let shouldIgnore = false
if (options.ignorePattern.length) {

if (
options.customIgnore.length &&
options.customIgnore.some(fn => fn(node, context.filename))
) {
shouldIgnore = true
}

if (!shouldIgnore && options.ignorePattern.length) {
let varParent = getNodeParent(node, ['VariableDeclarator', 'Property'])
let parentId =
varParent?.type === 'VariableDeclarator'
Expand Down
179 changes: 178 additions & 1 deletion test/sort-objects.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2866,8 +2866,185 @@ describe(RULE_NAME, () => {
},
],
},
{
code: dedent`
const buttonStyles = {
background: "palevioletred",
display: 'flex',
flexDirection: 'column',
width: "50px",
height: "50px",
}
`,
options: [
{
customIgnore: [
node => {
if (
node.parent.type === 'VariableDeclarator' &&
node.parent.id.type === 'Identifier'
) {
return node.parent.id.name === 'buttonStyles'
}
return false
},
],
},
],
},
],
invalid: [
{
code: dedent`
export default {
methods: {
foo() {},
bar() {},
baz() {},
},
data() {
return {
background: "palevioletred",
display: 'flex',
flexDirection: 'column',
width: "50px",
height: "50px",
}
},
}
`,
output: dedent`
export default {
data() {
return {
background: "palevioletred",
display: 'flex',
flexDirection: 'column',
width: "50px",
height: "50px",
}
},
methods: {
foo() {},
bar() {},
baz() {},
},
}
`,
options: [
{
ignorePattern: ['data', 'methods'],
},
],
errors: [
{
messageId: 'unexpectedObjectsOrder',
data: {
left: 'methods',
right: 'data',
},
},
],
},
{
code: dedent`
const buttonStyles = {
background: "palevioletred",
display: 'flex',
flexDirection: 'column',
width: "50px",
height: "50px",
}
`,
output: dedent`
const buttonStyles = {
background: "palevioletred",
display: 'flex',
flexDirection: 'column',
height: "50px",
width: "50px",
}
`,
options: [
{
customIgnore: [() => false],
},
],
errors: [
{
messageId: 'unexpectedObjectsOrder',
data: {
left: 'width',
right: 'height',
},
},
],
},
],
})

ruleTester.run(`${RULE_NAME}: allow to use for destructuring only`, rule, {
valid: [
{
code: dedent`
let obj = {
c: 'c',
b: 'b',
a: 'a',
}
let { a, b, c } = obj
`,
options: [
{
customIgnore: [node => node.type !== 'ObjectPattern'],
},
],
},
],
invalid: [
{
code: dedent`
let obj = {
c: 'c',
b: 'b',
a: 'a',
}
let { c, b, a } = obj
`,
output: dedent`
let obj = {
c: 'c',
b: 'b',
a: 'a',
}
let { a, b, c } = obj
`,
options: [
{
customIgnore: [node => node.type !== 'ObjectPattern'],
},
],
errors: [
{
messageId: 'unexpectedObjectsOrder',
data: {
left: 'c',
right: 'b',
},
},
{
messageId: 'unexpectedObjectsOrder',
data: {
left: 'b',
right: 'a',
},
},
],
},
],
invalid: [],
})
})
})

0 comments on commit 4fa2b3e

Please sign in to comment.