prettier-plugin-sort 1.0.1 → 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 -115
- package/README.zh.md +167 -117
- package/dist/index.d.ts +2 -2
- package/dist/index.js +480 -96
- 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 +11 -4
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`.
|
|
103
|
-
|
|
104
|
-
The plugin removes duplicate entries and appends omitted default groups in their default order. The default configuration does not include `internal`, so it sorts last unless explicitly added.
|
|
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 |
|
|
105
67
|
|
|
106
|
-
|
|
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`.
|
|
107
69
|
|
|
108
|
-
|
|
109
|
-
{
|
|
110
|
-
"plugins": ["prettier-plugin-sort"],
|
|
111
|
-
"esmImportGroups": [
|
|
112
|
-
"builtin",
|
|
113
|
-
"external",
|
|
114
|
-
"internal",
|
|
115
|
-
"parent",
|
|
116
|
-
"sibling",
|
|
117
|
-
"index"
|
|
118
|
-
]
|
|
119
|
-
}
|
|
120
|
-
```
|
|
70
|
+
The table also shows the default order. Duplicate entries are removed automatically, and omitted default groups are appended in their default order.
|
|
121
71
|
|
|
122
|
-
The plugin
|
|
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.
|
|
123
73
|
|
|
124
|
-
|
|
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,27 +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
|
-
`import type { T }` and `import { type T }` have different runtime behavior under [`verbatimModuleSyntax`](https://www.typescriptlang.org/tsconfig/verbatimModuleSyntax.html). 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.
|
|
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
|
-
|
|
149
|
-
- Side-effect import order can affect CSS cascading or polyfill loading, so these imports are not sorted. They keep their relative positions and separate the sorting segments around them.
|
|
150
|
-
- A declaration marked with `prettier-ignore` stays unchanged. Imports before and after it are sorted separately.
|
|
151
|
-
- A standalone comment separates the imports before and after it. A comment attached to an import moves with that declaration.
|
|
152
|
-
- The plugin preserves shebangs, Prettier file pragmas, and position-sensitive ESLint directives.
|
|
153
|
-
- 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.
|
|
154
96
|
|
|
155
97
|
## Export sorting
|
|
156
98
|
|
|
157
|
-
`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.
|
|
158
100
|
|
|
159
101
|
Before sorting:
|
|
160
102
|
|
|
@@ -169,11 +111,13 @@ After sorting:
|
|
|
169
111
|
export { type FC, useEffect, useState } from 'react';
|
|
170
112
|
```
|
|
171
113
|
|
|
172
|
-
|
|
114
|
+
Export declarations themselves are not moved or merged.
|
|
173
115
|
|
|
174
116
|
## `package.json` sorting
|
|
175
117
|
|
|
176
|
-
`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`.
|
|
177
121
|
|
|
178
122
|
Before sorting:
|
|
179
123
|
|
|
@@ -185,7 +129,8 @@ Before sorting:
|
|
|
185
129
|
"dependencies": {
|
|
186
130
|
"typescript": "^7.0.0",
|
|
187
131
|
"prettier": "^3.9.0"
|
|
188
|
-
}
|
|
132
|
+
},
|
|
133
|
+
"$schema": "https://json.schemastore.org/package.json"
|
|
189
134
|
}
|
|
190
135
|
```
|
|
191
136
|
|
|
@@ -193,6 +138,7 @@ After sorting:
|
|
|
193
138
|
|
|
194
139
|
```json
|
|
195
140
|
{
|
|
141
|
+
"$schema": "https://json.schemastore.org/package.json",
|
|
196
142
|
"name": "example",
|
|
197
143
|
"version": "1.0.0",
|
|
198
144
|
"dependencies": {
|
|
@@ -202,11 +148,123 @@ After sorting:
|
|
|
202
148
|
}
|
|
203
149
|
```
|
|
204
150
|
|
|
205
|
-
|
|
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`.
|
|
206
264
|
|
|
207
265
|
## TypeScript configuration
|
|
208
266
|
|
|
209
|
-
The
|
|
267
|
+
The plugin also exports the `SortOptions`, `ImportGroup`, and `TypeImportStyle` types for use in TypeScript configuration files:
|
|
210
268
|
|
|
211
269
|
```typescript
|
|
212
270
|
import { type Config } from 'prettier';
|
|
@@ -214,14 +272,6 @@ import { type SortOptions } from 'prettier-plugin-sort';
|
|
|
214
272
|
|
|
215
273
|
export default {
|
|
216
274
|
plugins: ['prettier-plugin-sort'],
|
|
217
|
-
esmImportGroups: [
|
|
218
|
-
'builtin',
|
|
219
|
-
'external',
|
|
220
|
-
'internal',
|
|
221
|
-
'parent',
|
|
222
|
-
'sibling',
|
|
223
|
-
'index',
|
|
224
|
-
],
|
|
225
275
|
esmImportTypeStyle: 'inline-last',
|
|
226
276
|
} satisfies Config & SortOptions;
|
|
227
277
|
```
|