Skip to content

Commit

Permalink
feat: add sort-svelte-attributes rule
Browse files Browse the repository at this point in the history
  • Loading branch information
azat-io committed Sep 4, 2023
1 parent 10d357c commit 409295e
Show file tree
Hide file tree
Showing 8 changed files with 1,829 additions and 33 deletions.
31 changes: 16 additions & 15 deletions docs/rules/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,21 @@ description: ESLint Plugin Perfectionist list of rules

🔧 Automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/user-guide/command-line-interface#--fix).

| Name | Description | 🔧 |
| :------------------------------------------------ | :------------------------------------------ | :- |
| [sort-array-includes](/rules/sort-array-includes) | enforce sorted arrays before include method | 🔧 |
| [sort-classes](/rules/sort-classes) | enforce sorted classes | 🔧 |
| [sort-enums](/rules/sort-enums) | enforce sorted TypeScript enums | 🔧 |
| [sort-exports](/rules/sort-exports) | enforce sorted exports | 🔧 |
| [sort-imports](/rules/sort-imports) | enforce sorted imports | 🔧 |
| [sort-interfaces](/rules/sort-interfaces) | enforce sorted interface properties | 🔧 |
| [sort-jsx-props](/rules/sort-jsx-props) | enforce sorted JSX props | 🔧 |
| [sort-maps](/rules/sort-maps) | enforce sorted Map elements | 🔧 |
| [sort-named-exports](/rules/sort-named-exports) | enforce sorted named exports | 🔧 |
| [sort-named-imports](/rules/sort-named-imports) | enforce sorted named imports | 🔧 |
| [sort-object-types](/rules/sort-object-types) | enforce sorted object types | 🔧 |
| [sort-objects](/rules/sort-objects) | enforce sorted objects | 🔧 |
| [sort-union-types](/rules/sort-union-types) | enforce sorted union types | 🔧 |
| Name | Description | 🔧 |
| :------------------------------------------------------ | :------------------------------------------ | :- |
| [sort-array-includes](/rules/sort-array-includes) | enforce sorted arrays before include method | 🔧 |
| [sort-classes](/rules/sort-classes) | enforce sorted classes | 🔧 |
| [sort-enums](/rules/sort-enums) | enforce sorted TypeScript enums | 🔧 |
| [sort-exports](/rules/sort-exports) | enforce sorted exports | 🔧 |
| [sort-imports](/rules/sort-imports) | enforce sorted imports | 🔧 |
| [sort-interfaces](/rules/sort-interfaces) | enforce sorted interface properties | 🔧 |
| [sort-jsx-props](/rules/sort-jsx-props) | enforce sorted JSX props | 🔧 |
| [sort-maps](/rules/sort-maps) | enforce sorted Map elements | 🔧 |
| [sort-named-exports](/rules/sort-named-exports) | enforce sorted named exports | 🔧 |
| [sort-named-imports](/rules/sort-named-imports) | enforce sorted named imports | 🔧 |
| [sort-object-types](/rules/sort-object-types) | enforce sorted object types | 🔧 |
| [sort-objects](/rules/sort-objects) | enforce sorted objects | 🔧 |
| [sort-svelte-attributes](/rules/sort-svelte-attributes) | enforce sorted union types | 🔧 |
| [sort-union-types](/rules/sort-union-types) | enforce sorted union types | 🔧 |

<!-- end auto-generated rules list -->
214 changes: 214 additions & 0 deletions docs/rules/sort-svelte-attributes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
---
title: sort-svelte-attributes
description: ESLint Plugin Perfectionist rule which enforce sorted attributes in Svelte elements
---

# sort-svelte-attributes

💼 This rule is enabled in the following [configs](/configs/): `recommended-alphabetical`, `recommended-line-length`, `recommended-natural`.

🔧 This rule is automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix).

<!-- end auto-generated rule header -->

## 📖 Rule Details

Enforce sorted attributes in Svelte elements.

It's **safe**. The rule considers spread elements in an attributes list and does not break component functionality.

:::info Important
If you use the [`sort-attributes`](https://sveltejs.github.io/eslint-plugin-svelte/rules/sort-attributes/) rule from the [`eslint-plugin-svelte`](https://sveltejs.github.io/eslint-plugin-svelte) plugin, it is highly recommended to [disable it](https://eslint.org/docs/latest/use/configure/rules#using-configuration-files-1) to avoid conflicts.
:::

## 💡 Examples

::: code-group

<!-- prettier-ignore -->
```svelte [Alphabetical and Natural Sorting]
// ❌ Incorrect
<Button
size="s"
type="button"
on:click={() => console.log("Clicked")}
color="primary"
disabled={false}
variant="solid"
>
Click me
</Button>
// ✅ Correct
<Button
color="primary"
disabled={false}
on:click={() => console.log("Clicked")}
size="s"
type="button"
variant="solid"
>
Click me
</Button>
```

```svelte [Sorting by Line Length]
// ❌ Incorrect
<Button
size="s"
type="button"
on:click={() => console.log("Clicked")}
color="primary"
disabled={false}
variant="solid"
>
Click me
</Button>
// ✅ Correct
<Button
on:click={() => console.log("Clicked")}
disabled={false}
variant="solid"
color="primary"
type="button"
size="s"
>
Click me
</Button>
```

:::

## 🔧 Options

This rule accepts an options object with the following properties:

```ts
type Group =
| 'multiline'
| 'shorthand'
| 'svelte-shorthand'
| 'unknown'

interface Options {
type?: 'alphabetical' | 'natural' | 'line-length'
order?: 'asc' | 'desc'
'ignore-case'?: boolean
groups?: (Group | Group[])[]
'custom-groups': { [key in T[number]]: string[] | string }
}
```

### type

<sub>(default: `'alphabetical'`)</sub>

- `alphabetical` - sort alphabetically.
- `natural` - sort in natural order.
- `line-length` - sort by code line length.

### order

<sub>(default: `'asc'`)</sub>

- `asc` - enforce properties to be in ascending order.
- `desc` - enforce properties to be in descending order.

### ignore-case

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

Only affects alphabetical and natural sorting. When `true` the rule ignores the case-sensitivity of the order.

### groups

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

You can set up a list of Svelte attribute groups for sorting. Groups can be combined. There are predefined groups: `'multiline'`, `'shorthand'`, `'svelte-shorthand'`.

### custom-groups

<sub>(default: `{}`)</sub>

You can define your own groups for Svelte attributes. The [minimatch](https://github.com/isaacs/minimatch) library is used for pattern matching.

Example:

```
{
"custom-groups": {
"callback": "on*"
}
}
```

## ⚙️ Usage

:::info Important
In order to start using this rule, you need to install additional dependencies:

- `svelte`
- `svelte-eslint-parser`
:::

::: code-group

```json [Legacy Config]
// .eslintrc
{
"plugins": ["perfectionist"],
"rules": {
"perfectionist/sort-svelte-attributes": [
"error",
{
"type": "natural",
"order": "asc",
"groups": [
"multiline",
"unknown",
["shorthand", "svelte-shorthand"]
]
}
]
}
}
```

```js [Flat Config]
// eslint.config.js
import perfectionist from 'eslint-plugin-perfectionist'

export default [
{
plugins: {
perfectionist,
},
rules: {
'perfectionist/sort-svelte-attributes': [
'error',
{
type: 'natural',
order: 'asc',
groups: [
'multiline',
'unknown',
['shorthand', 'svelte-shorthand'],
],
},
],
},
},
]
```

:::

## 🚀 Version

Coming soon.

## 📚 Resources

- [Rule source](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/rules/sort-svelte-attributes.ts)
- [Test source](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/test/sort-svelte-attributes.test.ts)
5 changes: 4 additions & 1 deletion index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import sortSvelteAttributes, { RULE_NAME as sortSvelteAttributesName } from './rules/sort-svelte-attributes'
import sortArrayIncludes, { RULE_NAME as sortArrayIncludesName } from './rules/sort-array-includes'
import sortNamedImports, { RULE_NAME as sortNamedImportsName } from './rules/sort-named-imports'
import sortNamedExports, { RULE_NAME as sortNamedExportsName } from './rules/sort-named-exports'
Expand Down Expand Up @@ -90,8 +91,9 @@ let createConfigWithOptions = (options: {
'spread-last': true,
},
],
[sortNamedImportsName]: ['error'],
[sortSvelteAttributesName]: ['error'],
[sortNamedExportsName]: ['error'],
[sortNamedImportsName]: ['error'],
[sortObjectTypesName]: ['error'],
[sortUnionTypesName]: ['error'],
[sortInterfacesName]: ['error'],
Expand Down Expand Up @@ -125,6 +127,7 @@ export default {
[sortNamedImportsName]: sortNamedImports,
[sortObjectTypesName]: sortObjectTypes,
[sortObjectsName]: sortObjects,
[sortSvelteAttributesName]: sortSvelteAttributes,
[sortUnionTypesName]: sortUnionTypes,
},
configs: {
Expand Down
14 changes: 13 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,18 @@
},
"./package.json": "./package.json"
},
"peerDependenciesMeta": {
"svelte": {
"optional": true
},
"svelte-eslint-parser": {
"optional": true
}
},
"peerDependencies": {
"eslint": ">=8.0.0"
"eslint": ">=8.0.0",
"svelte": ">=3.0.0",
"svelte-eslint-parser": "^0.32.0"
},
"dependencies": {
"@typescript-eslint/types": "^5.62.0",
Expand Down Expand Up @@ -87,6 +97,8 @@
"eslint-plugin-vitest": "^0.2.6",
"simple-git-hooks": "^2.8.1",
"sitemap": "^7.1.1",
"svelte": "^4.1.1",
"svelte-eslint-parser": "^0.32.2",
"ts-dedent": "^2.2.0",
"typescript": "^5.1.6",
"vite": "^4.4.4",
Expand Down

0 comments on commit 409295e

Please sign in to comment.