prettier-plugin-sort 1.0.1 → 1.1.1

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 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
- ## Scope
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
- The plugin groups and sorts top-level static imports. It also sorts the specifiers inside braces. Import specifiers that use `as` are sorted by their local names.
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
- The plugin leaves dynamic `import()` calls and import-like text in strings or comments unchanged. Set `esmImportSort` to `false` to disable all import sorting.
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` | Module paths beginning with `/`, `~`, `@/`, or `#` |
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 from `compilerOptions.paths` in the TypeScript project containing the current file |
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
- Projects that use one of these path aliases can add `internal`:
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
- ```json
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 does not read `compilerOptions.paths` or resolve aliases from bundler configuration.
72
+ The plugin searches upward from the current file for the nearest `tsconfig.json`, then uses `files`, `include`, and `exclude` to select the TypeScript project containing the file, following `references` when necessary. Each project is resolved through `extends` before matching the file and reading `compilerOptions.paths`. Only `paths` from the selected project are used to classify `internal`; `paths` from other referenced projects are not merged. Non-relative paths not declared there remain `external`. The catch-all pattern `*` is ignored because it cannot distinguish project modules from third-party packages.
123
73
 
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 and accepts four values:
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. Type-only default and namespace imports keep their original form.
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
- ### Merging and sorting boundaries
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
- With `esmImportMerge` enabled, imports from the same module are merged when it is safe to do so.
91
+ ### Merging
144
92
 
145
- The plugin does not merge imports with different import attributes, comments that cannot move safely, or conflicting default or namespace bindings. Side-effect imports also remain separate.
93
+ With `esmImportMerge` enabled, imports from the same module are merged when safe.
146
94
 
147
- Sorting never crosses these boundaries:
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 are sorted by their exported names.
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
- The plugin does not move or merge export declarations. If an export list contains comments, the declaration remains unchanged to preserve comment placement.
114
+ Export declarations themselves are not moved or merged.
173
115
 
174
116
  ## `package.json` sorting
175
117
 
176
- `package.json` field order follows [the default rules from sort-package-json 4.0.0](https://github.com/keithamus/sort-package-json/blob/v4.0.0/defaultRules.md). Nested content such as `scripts`, `exports`, and dependency fields follows the same version's rules.
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
- Setting `packageSort` to `false` disables key sorting only. Prettier still formats the file as usual.
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 package also exports `SortOptions`, `ImportGroup`, and `TypeImportStyle` for use in TypeScript configuration files:
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
  ```