prettier-plugin-sort 1.0.0 → 1.1.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.
- package/README.md +165 -113
- package/README.zh.md +167 -115
- package/dist/index.d.ts +2 -2
- package/dist/index.js +540 -145
- package/dist/options.d.ts +71 -7
- package/dist/parser-ast.d.ts +11 -3
- package/dist/sort-exports.d.ts +2 -2
- package/dist/sort-imports.d.ts +4 -4
- package/dist/sort-tsconfig.d.ts +6 -0
- package/dist/utils/package-rules.d.ts +1 -0
- package/dist/utils/tsconfig-rules.d.ts +16 -0
- package/package.json +16 -10
package/README.md
CHANGED
|
@@ -1,12 +1,33 @@
|
|
|
1
1
|
# prettier-plugin-sort
|
|
2
2
|
|
|
3
|
-
A [Prettier](https://prettier.io/) plugin focused on sorting.
|
|
3
|
+
A [Prettier](https://prettier.io/) plugin focused on sorting code and configuration files.
|
|
4
4
|
|
|
5
5
|
- Sort top-level `import` and `export { ... }` in JavaScript, TypeScript, and Flow
|
|
6
6
|
- Sort fields in `package.json`
|
|
7
|
+
- Sort fields in `tsconfig.json`
|
|
7
8
|
|
|
8
9
|
Read this in other languages: English | [中文](./README.zh.md)
|
|
9
10
|
|
|
11
|
+
## Preview
|
|
12
|
+
|
|
13
|
+
Alongside Prettier's regular formatting, the plugin sorts relevant declarations and fields. For example:
|
|
14
|
+
|
|
15
|
+
<!-- prettier-ignore -->
|
|
16
|
+
```javascript
|
|
17
|
+
import App from './App';
|
|
18
|
+
import { createRoot } from 'react-dom/client';
|
|
19
|
+
import { StrictMode } from 'react';
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Are formatted as:
|
|
23
|
+
|
|
24
|
+
```javascript
|
|
25
|
+
import { StrictMode } from 'react';
|
|
26
|
+
import { createRoot } from 'react-dom/client';
|
|
27
|
+
|
|
28
|
+
import App from './App';
|
|
29
|
+
```
|
|
30
|
+
|
|
10
31
|
## Install
|
|
11
32
|
|
|
12
33
|
Requires Prettier 3.9 or newer.
|
|
@@ -23,109 +44,38 @@ Add the plugin to your Prettier config:
|
|
|
23
44
|
}
|
|
24
45
|
```
|
|
25
46
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
ES module sorting supports these Prettier parsers:
|
|
29
|
-
|
|
30
|
-
- `babel`
|
|
31
|
-
- `babel-flow`
|
|
32
|
-
- `babel-ts`
|
|
33
|
-
- `typescript`
|
|
34
|
-
- `flow`
|
|
35
|
-
- `acorn`
|
|
36
|
-
- `espree`
|
|
37
|
-
- `meriyah`
|
|
38
|
-
|
|
39
|
-
The same sorting also applies to **embedded** JavaScript and TypeScript in Vue or Markdown.
|
|
40
|
-
|
|
41
|
-
The plugin only handles ES module syntax. CommonJS `require()` and `module.exports`, along with TypeScript `export =`, remain unchanged.
|
|
42
|
-
|
|
43
|
-
`package.json` sorting is enabled for these Prettier parsers:
|
|
44
|
-
|
|
45
|
-
- `json`
|
|
46
|
-
- `json-stringify`
|
|
47
|
-
|
|
48
|
-
Sorting is enabled only when the file is named `package.json`.
|
|
49
|
-
|
|
50
|
-
## Options
|
|
51
|
-
|
|
52
|
-
| Option | Type | Default | Description |
|
|
53
|
-
| ------------------------ | ----------------- | ------------------------------------------------------- | ------------------------------------------------------------------------ |
|
|
54
|
-
| `esmImportSort` | `boolean` | `true` | Group and sort top-level static imports and the specifiers inside braces |
|
|
55
|
-
| `esmImportGroups` | `ImportGroup[]` | `["builtin", "external", "parent", "sibling", "index"]` | Set the order of import groups |
|
|
56
|
-
| `esmImportSeparation` | `boolean` | `true` | Add blank lines between groups and above and below side-effect imports |
|
|
57
|
-
| `esmImportTypeStyle` | `TypeImportStyle` | `"separate"` | Control the form and order of type-only imports |
|
|
58
|
-
| `esmImportMerge` | `boolean` | `true` | Safely merge imports from the same module |
|
|
59
|
-
| `esmExportSpecifierSort` | `boolean` | `true` | Sort specifiers inside `export { ... }` |
|
|
60
|
-
| `packageSort` | `boolean` | `true` | Sort fields in `package.json` |
|
|
47
|
+
Continue running Prettier as usual after adding the plugin. Every sorting feature is enabled by default and can be adjusted independently.
|
|
61
48
|
|
|
62
49
|
## Import sorting
|
|
63
50
|
|
|
64
|
-
|
|
51
|
+
Top-level static imports are first gathered at the location of the first import, then grouped and sorted by module source. Named imports inside braces are also sorted by name, with aliased imports using their local names.
|
|
65
52
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
The plugin collects static imports separated by other top-level statements at the first import position, then sorts them.
|
|
69
|
-
|
|
70
|
-
Before sorting:
|
|
71
|
-
|
|
72
|
-
<!-- prettier-ignore -->
|
|
73
|
-
```typescript
|
|
74
|
-
import App from './App';
|
|
75
|
-
import fs from 'node:fs';
|
|
76
|
-
import react from 'react';
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
After sorting:
|
|
80
|
-
|
|
81
|
-
```typescript
|
|
82
|
-
import fs from 'node:fs';
|
|
83
|
-
|
|
84
|
-
import react from 'react';
|
|
85
|
-
|
|
86
|
-
import App from './App';
|
|
87
|
-
```
|
|
53
|
+
Dynamic `import()` calls and import-like text in strings or comments are left untouched. Set `esmImportSort` to `false` to disable all import sorting.
|
|
88
54
|
|
|
89
55
|
### Grouping
|
|
90
56
|
|
|
91
57
|
`esmImportGroups` accepts these values:
|
|
92
58
|
|
|
93
|
-
| Group | Matches
|
|
94
|
-
| ---------- |
|
|
95
|
-
| `builtin` | Modules beginning with `node:` or `bun:`, plus `bun`
|
|
96
|
-
| `external` | Packages and module paths not matched by any other group
|
|
97
|
-
| `internal` |
|
|
98
|
-
| `parent` | Parent-relative paths such as `../utils`
|
|
99
|
-
| `sibling` | Sibling paths such as `./Button`
|
|
100
|
-
| `index` | `.`, `./`, `./index`, and `./index` with an optional extension
|
|
101
|
-
|
|
102
|
-
Modern Node.js code should reference built-ins explicitly with [`node:` URLs](https://nodejs.org/api/esm.html#node-imports). The plugin also classifies only `node:`-prefixed Node.js built-ins as `builtin`. Module specifiers without the prefix, such as `fs` and `path`, belong to `external`.
|
|
59
|
+
| Group | Matches |
|
|
60
|
+
| ---------- | ------------------------------------------------------------------ |
|
|
61
|
+
| `builtin` | Modules beginning with `node:` or `bun:`, plus `bun` |
|
|
62
|
+
| `external` | Packages and module paths not matched by any other group |
|
|
63
|
+
| `internal` | Path aliases defined by `compilerOptions.paths` in `tsconfig.json` |
|
|
64
|
+
| `parent` | Parent-relative paths such as `../utils` |
|
|
65
|
+
| `sibling` | Sibling paths such as `./Button` |
|
|
66
|
+
| `index` | `.`, `./`, `./index`, and `./index` with an optional extension |
|
|
103
67
|
|
|
104
|
-
|
|
68
|
+
Modern Node.js code should reference built-ins explicitly with [`node:` URLs](https://nodejs.org/api/esm.html#node-imports). The plugin also classifies only `node:`-prefixed modules as `builtin`. Module specifiers without the prefix, such as `fs` and `path`, belong to `external`.
|
|
105
69
|
|
|
106
|
-
|
|
70
|
+
The table also shows the default order. Duplicate entries are removed automatically, and omitted default groups are appended in their default order.
|
|
107
71
|
|
|
108
|
-
|
|
109
|
-
{
|
|
110
|
-
"plugins": ["prettier-plugin-sort"],
|
|
111
|
-
"esmImportGroups": [
|
|
112
|
-
"builtin",
|
|
113
|
-
"external",
|
|
114
|
-
"internal",
|
|
115
|
-
"parent",
|
|
116
|
-
"sibling",
|
|
117
|
-
"index"
|
|
118
|
-
]
|
|
119
|
-
}
|
|
120
|
-
```
|
|
72
|
+
The plugin searches upward from the current file for the nearest `tsconfig.json` and identifies `internal` imports from the resolved `compilerOptions.paths`. Inherited `paths` are supported. Non-relative paths not declared in `paths` remain `external`. The catch-all pattern `*` is ignored because it cannot distinguish project modules from third-party packages.
|
|
121
73
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
Set `esmImportSeparation` to `false` to remove blank lines between groups and above and below side-effect imports.
|
|
74
|
+
With `esmImportSeparation` set to `false`, blank lines are removed both between groups and around side-effect imports.
|
|
125
75
|
|
|
126
76
|
### Type-only import style
|
|
127
77
|
|
|
128
|
-
`esmImportTypeStyle` controls how type-only imports are written
|
|
78
|
+
`esmImportTypeStyle` controls how type-only imports are written. It accepts these four values:
|
|
129
79
|
|
|
130
80
|
| Value | Input: `import { c, type B, a } from 'mod'` |
|
|
131
81
|
| -------------- | ---------------------------------------------------------------- |
|
|
@@ -134,25 +84,19 @@ Set `esmImportSeparation` to `false` to remove blank lines between groups and ab
|
|
|
134
84
|
| `inline-last` | `import { a, c, type B } from 'mod';` |
|
|
135
85
|
| `mixed` | `import { a, type B, c } from 'mod';` |
|
|
136
86
|
|
|
137
|
-
`separate` is the default.
|
|
138
|
-
|
|
139
|
-
### Merging and sorting boundaries
|
|
87
|
+
`separate` is the default. `import type T from 'mod'` and `import type * as ns from 'mod'` keep their original form.
|
|
140
88
|
|
|
141
|
-
|
|
89
|
+
Under [`verbatimModuleSyntax`](https://www.typescriptlang.org/tsconfig/verbatimModuleSyntax.html), `import type { T }` and `import { type T }` have different runtime behavior. The plugin converts between them only when the same module also has a value import. Otherwise, it preserves the original form to avoid changing module loading behavior.
|
|
142
90
|
|
|
143
|
-
|
|
91
|
+
### Merging
|
|
144
92
|
|
|
145
|
-
|
|
93
|
+
With `esmImportMerge` enabled, imports from the same module are merged when safe.
|
|
146
94
|
|
|
147
|
-
|
|
148
|
-
- A declaration marked with `prettier-ignore` stays unchanged. Imports before and after it are sorted separately.
|
|
149
|
-
- A standalone comment separates the imports before and after it. A comment attached to an import moves with that declaration.
|
|
150
|
-
- The plugin preserves shebangs, Prettier file pragmas, and position-sensitive ESLint directives.
|
|
151
|
-
- Specialized declarations such as `import source`, `import defer`, and Flow `import typeof` may be reordered as a whole. The plugin never rewrites or merges them.
|
|
95
|
+
Imports are not merged when their import attributes differ, comments cannot move safely, or default and namespace bindings conflict. Side-effect imports always remain separate.
|
|
152
96
|
|
|
153
97
|
## Export sorting
|
|
154
98
|
|
|
155
|
-
`esmExportSpecifierSort` sorts top-level `export { ... }` and `export type { ... }` entries by name. Aliased entries
|
|
99
|
+
`esmExportSpecifierSort` sorts top-level `export { ... }` and `export type { ... }` entries by name. Aliased entries use their exported names.
|
|
156
100
|
|
|
157
101
|
Before sorting:
|
|
158
102
|
|
|
@@ -167,11 +111,13 @@ After sorting:
|
|
|
167
111
|
export { type FC, useEffect, useState } from 'react';
|
|
168
112
|
```
|
|
169
113
|
|
|
170
|
-
|
|
114
|
+
Export declarations themselves are not moved or merged.
|
|
171
115
|
|
|
172
116
|
## `package.json` sorting
|
|
173
117
|
|
|
174
|
-
`package.json
|
|
118
|
+
`$schema` comes first in `package.json`. Other fields follow the default rules from [sort-package-json 4.0.0](https://github.com/keithamus/sort-package-json/blob/v4.0.0/defaultRules.md). These rules also determine the internal order of `scripts` and `exports`.
|
|
119
|
+
|
|
120
|
+
npm sorts dependency names with `String.prototype.localeCompare(..., 'en')`. pnpm uses the default order of `Array.prototype.sort()`, while Yarn compares strings with `<` and `>`. The latter two use UTF-16 code unit ordering, so punctuation can produce different results. For example, npm places `a_b` before `a-b`, while pnpm and Yarn use the opposite order. Because `package.json` uses npm's definition as its canonical reference, the plugin always uses npm's dependency comparator. `sort-package-json` instead switches the dependency comparator based on the package manager. This is the only difference between the plugin's sorting rules and those of `sort-package-json`.
|
|
175
121
|
|
|
176
122
|
Before sorting:
|
|
177
123
|
|
|
@@ -183,7 +129,8 @@ Before sorting:
|
|
|
183
129
|
"dependencies": {
|
|
184
130
|
"typescript": "^7.0.0",
|
|
185
131
|
"prettier": "^3.9.0"
|
|
186
|
-
}
|
|
132
|
+
},
|
|
133
|
+
"$schema": "https://json.schemastore.org/package.json"
|
|
187
134
|
}
|
|
188
135
|
```
|
|
189
136
|
|
|
@@ -191,6 +138,7 @@ After sorting:
|
|
|
191
138
|
|
|
192
139
|
```json
|
|
193
140
|
{
|
|
141
|
+
"$schema": "https://json.schemastore.org/package.json",
|
|
194
142
|
"name": "example",
|
|
195
143
|
"version": "1.0.0",
|
|
196
144
|
"dependencies": {
|
|
@@ -200,11 +148,123 @@ After sorting:
|
|
|
200
148
|
}
|
|
201
149
|
```
|
|
202
150
|
|
|
203
|
-
|
|
151
|
+
Set `packageSort` to `false` to disable field sorting without affecting Prettier's regular formatting.
|
|
152
|
+
|
|
153
|
+
## `tsconfig.json` sorting
|
|
154
|
+
|
|
155
|
+
The [TypeScript Handbook inheritance examples](https://www.typescriptlang.org/docs/handbook/tsconfig-json#tsconfig-bases) place `extends` before other settings, while its [file configuration examples](https://www.typescriptlang.org/docs/handbook/tsconfig-json#examples) place `files`, `include`, and `exclude` after `compilerOptions`. The plugin follows this layout and places `$schema` first by common JSON Schema convention. The resulting order is `$schema`, `extends`, other top-level fields, `files`, `include`, and `exclude`. Other top-level fields keep their relative order.
|
|
156
|
+
|
|
157
|
+
Options in `compilerOptions` follow the groups and order from the [`tsc --init` template in TypeScript 5.8.3](https://github.com/microsoft/TypeScript/blob/v5.8.3/src/compiler/commandLineParser.ts). Objects and arrays inside individual options keep their original order.
|
|
158
|
+
|
|
159
|
+
Before sorting:
|
|
160
|
+
|
|
161
|
+
<!-- prettier-ignore -->
|
|
162
|
+
```json
|
|
163
|
+
{
|
|
164
|
+
"exclude": ["dist"],
|
|
165
|
+
"files": ["index.ts"],
|
|
166
|
+
"include": ["src"],
|
|
167
|
+
"compilerOptions": {
|
|
168
|
+
"strict": true,
|
|
169
|
+
"moduleResolution": "bundler",
|
|
170
|
+
"skipLibCheck": true,
|
|
171
|
+
"target": "ESNext",
|
|
172
|
+
"noEmit": true,
|
|
173
|
+
"module": "Preserve",
|
|
174
|
+
"lib": ["ESNext"],
|
|
175
|
+
"outDir": "dist",
|
|
176
|
+
"noUncheckedIndexedAccess": true
|
|
177
|
+
},
|
|
178
|
+
"extends": "./base.json",
|
|
179
|
+
"$schema": "https://json.schemastore.org/tsconfig"
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
After sorting:
|
|
184
|
+
|
|
185
|
+
```json
|
|
186
|
+
{
|
|
187
|
+
"$schema": "https://json.schemastore.org/tsconfig",
|
|
188
|
+
"extends": "./base.json",
|
|
189
|
+
"compilerOptions": {
|
|
190
|
+
"target": "ESNext",
|
|
191
|
+
"lib": ["ESNext"],
|
|
192
|
+
|
|
193
|
+
"module": "Preserve",
|
|
194
|
+
"moduleResolution": "bundler",
|
|
195
|
+
|
|
196
|
+
"noEmit": true,
|
|
197
|
+
"outDir": "dist",
|
|
198
|
+
|
|
199
|
+
"strict": true,
|
|
200
|
+
"noUncheckedIndexedAccess": true,
|
|
201
|
+
|
|
202
|
+
"skipLibCheck": true
|
|
203
|
+
},
|
|
204
|
+
"files": ["index.ts"],
|
|
205
|
+
"include": ["src"],
|
|
206
|
+
"exclude": ["dist"]
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
Groups are separated by a blank line by default. Set `tsconfigSeparation` to `false` to remove these blank lines.
|
|
211
|
+
|
|
212
|
+
`stableTypeOrdering`, added in TypeScript 6.0, and `deduplicatePackages`, added in TypeScript 7.0, are not part of the 5.8.3 template and are therefore placed last. Other options not found in the template are handled the same way and keep their relative order.
|
|
213
|
+
|
|
214
|
+
Set `tsconfigSort` to `false` to disable field sorting without affecting Prettier's regular formatting.
|
|
215
|
+
|
|
216
|
+
## Options
|
|
217
|
+
|
|
218
|
+
Every option and its default are listed below:
|
|
219
|
+
|
|
220
|
+
| Option | Type | Default | Description |
|
|
221
|
+
| ------------------------ | ----------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------------ |
|
|
222
|
+
| `esmImportSort` | `boolean` | `true` | Group and sort top-level static imports and the specifiers inside braces |
|
|
223
|
+
| `esmImportGroups` | `ImportGroup[]` | `["builtin", "external", "internal", "parent", "sibling", "index"]` | Set the order of import groups |
|
|
224
|
+
| `esmImportSeparation` | `boolean` | `true` | Add blank lines between groups and above and below side-effect imports |
|
|
225
|
+
| `esmImportTypeStyle` | `TypeImportStyle` | `"separate"` | Control the form and order of type-only imports |
|
|
226
|
+
| `esmImportMerge` | `boolean` | `true` | Safely merge imports from the same module |
|
|
227
|
+
| `esmExportSpecifierSort` | `boolean` | `true` | Sort specifiers inside `export { ... }` |
|
|
228
|
+
| `packageSort` | `boolean` | `true` | Sort fields in `package.json` |
|
|
229
|
+
| `tsconfigSort` | `boolean` | `true` | Sort fields in `tsconfig.json` |
|
|
230
|
+
| `tsconfigSeparation` | `boolean` | `true` | Add blank lines between `compilerOptions` categories |
|
|
231
|
+
|
|
232
|
+
## Comments and sorting boundaries
|
|
233
|
+
|
|
234
|
+
To preserve runtime semantics and comment ownership, the following content separates the surrounding imports into independent sorting segments:
|
|
235
|
+
|
|
236
|
+
- Side-effect imports have execution semantics. They are not sorted and separate the surrounding sorting segments.
|
|
237
|
+
- A declaration marked with `prettier-ignore` is left untouched. Imports before and after it are sorted separately.
|
|
238
|
+
- A standalone comment separates the surrounding imports, while a comment attached to an import moves with that declaration.
|
|
239
|
+
|
|
240
|
+
Shebangs, Prettier file pragmas, and position-sensitive ESLint directives stay in place. Specialized declarations such as `import source`, `import defer`, and Flow `import typeof` may move within their segment but are never rewritten or merged.
|
|
241
|
+
|
|
242
|
+
An `export { ... }` declaration containing comments is left untouched. Comments in `tsconfig.json` only prevent fields in the same layer from being sorted. Top-level comments do not affect `compilerOptions`, and comments in `compilerOptions` do not affect top-level fields.
|
|
243
|
+
|
|
244
|
+
## Supported files
|
|
245
|
+
|
|
246
|
+
ES module sorting supports these Prettier parsers:
|
|
247
|
+
|
|
248
|
+
- `babel`
|
|
249
|
+
- `babel-flow`
|
|
250
|
+
- `babel-ts`
|
|
251
|
+
- `typescript`
|
|
252
|
+
- `flow`
|
|
253
|
+
- `acorn`
|
|
254
|
+
- `espree`
|
|
255
|
+
- `meriyah`
|
|
256
|
+
|
|
257
|
+
JavaScript and TypeScript **embedded code** in files such as Vue and Markdown is also sorted through these parsers.
|
|
258
|
+
|
|
259
|
+
The plugin only handles ES module syntax. It does not modify CommonJS `require()` or `module.exports`, or TypeScript `export =`.
|
|
260
|
+
|
|
261
|
+
`package.json` sorting supports the `json` and `json-stringify` parsers and applies only to files named `package.json`.
|
|
262
|
+
|
|
263
|
+
`tsconfig.json` sorting supports the `json` parser. The file must be named `tsconfig.json` or `tsconfig.*.json`.
|
|
204
264
|
|
|
205
265
|
## TypeScript configuration
|
|
206
266
|
|
|
207
|
-
The
|
|
267
|
+
The plugin also exports the `SortOptions`, `ImportGroup`, and `TypeImportStyle` types for use in TypeScript configuration files:
|
|
208
268
|
|
|
209
269
|
```typescript
|
|
210
270
|
import { type Config } from 'prettier';
|
|
@@ -212,14 +272,6 @@ import { type SortOptions } from 'prettier-plugin-sort';
|
|
|
212
272
|
|
|
213
273
|
export default {
|
|
214
274
|
plugins: ['prettier-plugin-sort'],
|
|
215
|
-
esmImportGroups: [
|
|
216
|
-
'builtin',
|
|
217
|
-
'external',
|
|
218
|
-
'internal',
|
|
219
|
-
'parent',
|
|
220
|
-
'sibling',
|
|
221
|
-
'index',
|
|
222
|
-
],
|
|
223
275
|
esmImportTypeStyle: 'inline-last',
|
|
224
276
|
} satisfies Config & SortOptions;
|
|
225
277
|
```
|