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.zh.md CHANGED
@@ -1,15 +1,36 @@
1
1
  # prettier-plugin-sort
2
2
 
3
- 一个专注于排序的 [Prettier](https://prettier.io/) 插件。
3
+ 一个专注于代码、配置文件排序的 [Prettier](https://prettier.io/) 插件。
4
4
 
5
5
  - 排序 JavaScript、TypeScript 和 Flow 中的顶层 `import` 和 `export { ... }`
6
6
  - 排序 `package.json` 字段
7
+ - 排序 `tsconfig.json` 字段
7
8
 
8
9
  使用其他语言阅读:[English](./README.md) | 中文
9
10
 
11
+ ## 效果预览
12
+
13
+ 插件会在 Prettier 格式化文件时同时整理内容顺序。以 `import` 为例:
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
+ 格式化后会变成:
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
  ## 安装
11
32
 
12
- 需要 Prettier 3.9 或更高版本。
33
+ 要求 Prettier 3.9 或更高版本。
13
34
 
14
35
  ```shell
15
36
  npm i -D prettier prettier-plugin-sort
@@ -23,109 +44,38 @@ npm i -D prettier prettier-plugin-sort
23
44
  }
24
45
  ```
25
46
 
26
- ## 作用范围
27
-
28
- ES 模块排序支持以下 Prettier 解析器:
29
-
30
- - `babel`
31
- - `babel-flow`
32
- - `babel-ts`
33
- - `typescript`
34
- - `flow`
35
- - `acorn`
36
- - `espree`
37
- - `meriyah`
38
-
39
- 上述排序同样适用于这些解析器处理的**嵌入式**代码,例如 Vue 或 Markdown 中的 JavaScript 或 TypeScript 内容。
40
-
41
- 插件只处理 ES 模块语法。CommonJS 的 `require()`、`module.exports` 和 TypeScript `export =` 会保持不变。
42
-
43
- `package.json` 排序支持以下 Prettier 解析器:
44
-
45
- - `json`
46
- - `json-stringify`
47
-
48
- 仅当文件名为 `package.json` 时,才会启用排序。
49
-
50
- ## 配置项
51
-
52
- | 配置项 | 类型 | 默认值 | 作用 |
53
- | ------------------------ | ----------------- | ------------------------------------------------------- | --------------------------------------------------- |
54
- | `esmImportSort` | `boolean` | `true` | 分组并排序顶层静态 `import`,同时排列其中的具名导入 |
55
- | `esmImportGroups` | `ImportGroup[]` | `["builtin", "external", "parent", "sibling", "index"]` | 指定 `import` 分组顺序 |
56
- | `esmImportSeparation` | `boolean` | `true` | 在不同分组之间及副作用 `import` 的上下两侧留出空行 |
57
- | `esmImportTypeStyle` | `TypeImportStyle` | `"separate"` | 控制仅类型 `import` 的写法与顺序 |
58
- | `esmImportMerge` | `boolean` | `true` | 安全合并来自同一模块的 `import` |
59
- | `esmExportSpecifierSort` | `boolean` | `true` | 按名称排列 `export { ... }` 形式的导出列表 |
60
- | `packageSort` | `boolean` | `true` | 排序 `package.json` 字段 |
47
+ 之后照常运行 Prettier 即可。各项排序默认开启,可以通过配置项分别调整。
61
48
 
62
49
  ## `import` 排序
63
50
 
64
- 插件会分组并排序文件顶层的静态 `import`,同时排列其中的具名导入。带 `as` 的具名导入按本地名称排序。
51
+ 文件顶层的静态 `import` 会先集中到第一条 `import` 所在的位置,再按模块来源分组排序。花括号内的具名导入也会按名称排列,使用 `as` 时按本地名称排序。
65
52
 
66
- 插件不会处理动态 `import()`,也不会处理字符串和注释中类似 `import` 的内容。将 `esmImportSort` 设为 `false`,可以关闭所有 `import` 排序功能。
67
-
68
- 插件会把分散在其他顶层语句之间的静态 `import` 集中到第一条 `import` 所在位置,再进行排序。
69
-
70
- 排序前:
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
- 排序后:
80
-
81
- ```typescript
82
- import fs from 'node:fs';
83
-
84
- import react from 'react';
85
-
86
- import App from './App';
87
- ```
53
+ 动态 `import()` 以及字符串、注释中形似 `import` 的内容都不会改动。将 `esmImportSort` 设为 `false` 可关闭全部 `import` 排序。
88
54
 
89
55
  ### 分组
90
56
 
91
57
  `esmImportGroups` 支持以下分组:
92
58
 
93
- | 分组 | 匹配范围 |
94
- | ---------- | ------------------------------------------- |
95
- | `builtin` | 以 `node:`、`bun:` 开头的模块,以及 `bun` |
96
- | `external` | 第三方包,以及没有匹配其他分组的模块路径 |
97
- | `internal` | `/`、`~`、`@/` `#` 开头的模块路径 |
98
- | `parent` | `../utils` 这类指向上级目录的相对路径 |
99
- | `sibling` | `./Button` 这类指向同级目录的相对路径 |
100
- | `index` | `.`、`./`、`./index` 及带扩展名的 `./index` |
101
-
102
- 现代 Node.js 代码应使用 [`node:` URL](https://nodejs.org/api/esm.html#node-imports) 显式引用内置模块。本插件也只把带 `node:` 前缀的 Node.js 内置模块归入 `builtin`。`fs`、`path` 等未带前缀的内置模块名称归入 `external`。
103
-
104
- 插件会移除配置数组中的重复项,并按默认顺序追加未列出的默认分组。默认配置不包含 `internal`,因此它在未显式加入时排在最后。
59
+ | 分组 | 匹配范围 |
60
+ | ---------- | --------------------------------------------------------- |
61
+ | `builtin` | 以 `node:`、`bun:` 开头的模块,以及 `bun` |
62
+ | `external` | 第三方包,以及没有匹配其他分组的模块路径 |
63
+ | `internal` | `tsconfig.json` `compilerOptions.paths` 定义的路径别名 |
64
+ | `parent` | `../utils` 这类指向上级目录的相对路径 |
65
+ | `sibling` | `./Button` 这类指向同级目录的相对路径 |
66
+ | `index` | `.`、`./`、`./index` 及带扩展名的 `./index` |
105
67
 
106
- 项目使用上述路径别名时,可以手动加入 `internal`:
68
+ 现代 Node.js 代码应使用 [`node:` URL](https://nodejs.org/api/esm.html#node-imports) 显式引用内置模块。本插件也只把带 `node:` 前缀的内置模块归入 `builtin`。`fs`、`path` 等未带前缀的模块归入 `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
+ 默认顺序就是表中的顺序。配置数组会自动去重,遗漏的默认分组则按默认顺序补到末尾。
121
71
 
122
- 插件不会读取 `compilerOptions.paths`,也不会解析构建工具的别名配置。
72
+ 插件会从当前文件所在目录向上查找最近的 `tsconfig.json`,并根据解析后的 `compilerOptions.paths` 识别 `internal`。继承配置中的 `paths` 同样有效。没有在 `paths` 中声明的非相对路径仍归入 `external`。`*` 无法区分项目代码和第三方包,因此不会用于判断 `internal`。
123
73
 
124
- 如果不希望不同分组之间及副作用 `import` 的上下两侧留出空行,可以将 `esmImportSeparation` 设为 `false`。
74
+ `esmImportSeparation` 设为 `false` 后,分组之间和副作用 `import` 上下两侧都不再留空行。
125
75
 
126
- ### 仅类型 `import` 写法
76
+ ### 类型 `import` 写法
127
77
 
128
- `esmImportTypeStyle` 用来控制仅类型 `import` 的写法,共有四种取值:
78
+ `esmImportTypeStyle` 控制类型 `import` 的写法和顺序,支持以下四种值:
129
79
 
130
80
  | 配置值 | 输入 `import { c, type B, a } from 'mod'` 后的结果 |
131
81
  | -------------- | ---------------------------------------------------------------- |
@@ -134,27 +84,19 @@ import App from './App';
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`。包含默认导入或命名空间导入的仅类型 `import` 会保留原有形式。
138
-
139
- `import type { T }` 和 `import { type T }` 在 [`verbatimModuleSyntax`](https://www.typescriptlang.org/tsconfig/verbatimModuleSyntax.html) 下具有不同的运行时行为。仅当同一模块同时存在值导入时,插件才会在两种写法之间转换。否则保留原写法,避免改变模块的加载行为。
87
+ 默认值是 `separate`。`import type T from 'mod'` 和 `import type * as ns from 'mod'` 会保留原写法。
140
88
 
141
- ### 合并与排序边界
89
+ 启用 [`verbatimModuleSyntax`](https://www.typescriptlang.org/tsconfig/verbatimModuleSyntax.html) 后,`import type { T }` 和 `import { type T }` 的运行时行为并不相同。只有同一模块还存在值导入时,插件才会在两种写法之间转换,以免意外改变模块加载行为。
142
90
 
143
- 启用 `esmImportMerge` 后,来自同一模块的 `import` 会在安全的情况下合并。
91
+ ### 合并
144
92
 
145
- `import` 属性不同、注释无法安全移动,或者默认导入和命名空间导入存在冲突时,插件不会合并这些 `import`。副作用 `import` 也不会合并。
93
+ 启用 `esmImportMerge` 后,同一模块的 `import` 会在安全的前提下合并。
146
94
 
147
- 排序不会跨越以下边界:
148
-
149
- - 副作用 `import` 的顺序可能影响 CSS 层叠或兼容性补丁的加载,因此不会参与排序。它们会保持相对位置,并分隔前后的排序片段。
150
- - 带有 `prettier-ignore` 的声明保持不变,其前后的 `import` 分别排序。
151
- - 独立注释会分隔前后的 `import`。紧跟某条 `import` 的注释会和它一起移动。
152
- - 插件会保留文件开头的 `#!` 指令、Prettier 文件级指令和位置敏感的 ESLint 指令。
153
- - `import source`、`import defer`、Flow `import typeof` 等特殊声明可以整体参与排序。插件不会改写或合并这些声明。
95
+ `import` 属性不同、注释无法安全移动,或默认导入与命名空间导入发生冲突时,都不会合并。副作用 `import` 始终保持独立。
154
96
 
155
97
  ## `export` 排序
156
98
 
157
- `esmExportSpecifierSort` 会按名称排列顶层 `export { ... }` 和 `export type { ... }`。使用 `as` 时,按导出后的名称排序。
99
+ `esmExportSpecifierSort` 按名称排列顶层 `export { ... }` 和 `export type { ... }`。使用 `as` 时,以导出后的名称为准。
158
100
 
159
101
  排序前:
160
102
 
@@ -169,11 +111,13 @@ export { useState, useEffect, type FC } from 'react';
169
111
  export { type FC, useEffect, useState } from 'react';
170
112
  ```
171
113
 
172
- 插件不会移动或合并 `export` 声明。花括号内含有注释时,整条声明会保持原样,避免改变注释归属。
114
+ `export` 声明本身不会移动或合并。
173
115
 
174
116
  ## `package.json` 排序
175
117
 
176
- `package.json` 的字段顺序遵循 [sort-package-json 4.0.0 的默认规则](https://github.com/keithamus/sort-package-json/blob/v4.0.0/defaultRules.md)。`scripts`、`exports` 和依赖字段等内部内容也按该版本的规则排序。
118
+ `$schema` JSON Schema 的通行写法放在最前。其他字段遵循 [sort-package-json 4.0.0](https://github.com/keithamus/sort-package-json/blob/v4.0.0/defaultRules.md) 的默认规则,`scripts` 和 `exports` 的内部顺序也由这套规则决定。
119
+
120
+ npm 使用 `String.prototype.localeCompare(..., 'en')` 排列 dependency name,pnpm 使用 `Array.prototype.sort()` 的默认顺序,Yarn 则通过 `<` 和 `>` 比较字符串。后两种方式都采用 UTF-16 code unit order,因此包含 `-`、`_` 等符号的 dependency name 可能得到不同结果。例如 npm 将 `a_b` 排在 `a-b` 前,pnpm 和 Yarn 的顺序相反。由于 `package.json` 由 npm 定义,本插件以 npm 的排序行为为基准。`sort-package-json` 会根据 package manager 切换 dependency comparator,本插件则固定使用 npm comparator。这是本插件与 `sort-package-json` 排序规则的唯一差异。
177
121
 
178
122
  排序前:
179
123
 
@@ -185,7 +129,8 @@ export { type FC, useEffect, useState } from 'react';
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 @@ export { type FC, useEffect, useState } from 'react';
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 @@ export { type FC, useEffect, useState } from 'react';
202
148
  }
203
149
  ```
204
150
 
205
- 将 `packageSort` 设为 `false` 只会关闭字段排序,Prettier 仍会照常排版该文件。
151
+ 将 `packageSort` 设为 `false` 可关闭字段排序,不影响 Prettier 本身的排版。
152
+
153
+ ## `tsconfig.json` 排序
154
+
155
+ [TypeScript Handbook 的继承示例](https://www.typescriptlang.org/docs/handbook/tsconfig-json#tsconfig-bases) 将 `extends` 写在其他配置之前,[文件配置示例](https://www.typescriptlang.org/docs/handbook/tsconfig-json#examples) 则将 `files`、`include` 和 `exclude` 写在 `compilerOptions` 之后。本插件沿用这种布局,并按 JSON Schema 的通行写法将 `$schema` 放在最前。最终顺序为 `$schema`、`extends`、其他顶层字段、`files`、`include`、`exclude`,其他顶层字段之间的顺序不变。
156
+
157
+ `compilerOptions` 里的配置项按照 [TypeScript 5.8.3 的 `tsc --init` 模板](https://github.com/microsoft/TypeScript/blob/v5.8.3/src/compiler/commandLineParser.ts) 分组排序。配置项内的对象和数组保持原有顺序。
158
+
159
+ 排序前:
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
+ 排序后:
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
+ 不同分组之间默认留一个空行。将 `tsconfigSeparation` 设为 `false` 可去掉这些空行。
211
+
212
+ TypeScript 6.0 新增的 `stableTypeOrdering` 和 TypeScript 7.0 新增的 `deduplicatePackages` 不在 5.8.3 模板中,因此排在最后。其他未收录的配置项也按同样方式处理,彼此之间保留原有顺序。
213
+
214
+ 将 `tsconfigSort` 设为 `false` 可关闭字段排序,不影响 Prettier 本身的排版。
215
+
216
+ ## 配置项
217
+
218
+ 所有配置项及其默认值如下:
219
+
220
+ | 配置项 | 类型 | 默认值 | 作用 |
221
+ | ------------------------ | ----------------- | ------------------------------------------------------------------- | --------------------------------------------------- |
222
+ | `esmImportSort` | `boolean` | `true` | 分组并排序顶层静态 `import`,同时排列其中的具名导入 |
223
+ | `esmImportGroups` | `ImportGroup[]` | `["builtin", "external", "internal", "parent", "sibling", "index"]` | 指定 `import` 分组顺序 |
224
+ | `esmImportSeparation` | `boolean` | `true` | 在不同分组之间及副作用 `import` 的上下两侧留出空行 |
225
+ | `esmImportTypeStyle` | `TypeImportStyle` | `"separate"` | 控制类型 `import` 的写法与顺序 |
226
+ | `esmImportMerge` | `boolean` | `true` | 安全合并来自同一模块的 `import` |
227
+ | `esmExportSpecifierSort` | `boolean` | `true` | 按名称排列 `export { ... }` 形式的导出列表 |
228
+ | `packageSort` | `boolean` | `true` | 排序 `package.json` 字段 |
229
+ | `tsconfigSort` | `boolean` | `true` | 排序 `tsconfig.json` 字段 |
230
+ | `tsconfigSeparation` | `boolean` | `true` | 在 `compilerOptions` 分类之间留出空行 |
231
+
232
+ ## 注释与排序边界
233
+
234
+ 为了避免改变运行时语义或注释归属,以下内容会将前后的 `import` 分成独立的排序片段:
235
+
236
+ - 副作用 `import` 具有执行语义,不参与排序,并分隔前后的排序片段。
237
+ - 带有 `prettier-ignore` 的声明不会改动,其前后的 `import` 分别排序。
238
+ - 独立注释会分隔前后的 `import`,紧跟某条 `import` 的注释则随该声明一起移动。
239
+
240
+ 文件开头的 `#!`、Prettier 文件级指令和位置敏感的 ESLint 指令会留在原位。`import source`、`import defer`、Flow `import typeof` 等特殊声明可以随所在片段整体移动,但不会改写或合并。
241
+
242
+ `export { ... }` 内有注释时,整条声明保持原样。`tsconfig.json` 中的注释只会阻止同一层的字段排序。顶层注释不会影响 `compilerOptions`,`compilerOptions` 中的注释也不会影响顶层字段。
243
+
244
+ ## 支持范围
245
+
246
+ 以下 Prettier 解析器支持 ES 模块排序:
247
+
248
+ - `babel`
249
+ - `babel-flow`
250
+ - `babel-ts`
251
+ - `typescript`
252
+ - `flow`
253
+ - `acorn`
254
+ - `espree`
255
+ - `meriyah`
256
+
257
+ Vue、Markdown 等文件中的 JavaScript 和 TypeScript 的**嵌入式代码**也会通过这些解析器参与排序。
258
+
259
+ 插件只处理 ES 模块语法,不会改动 CommonJS 的 `require()`、`module.exports` 或 TypeScript 的 `export =`。
260
+
261
+ `package.json` 排序支持 `json` 和 `json-stringify` 解析器,只对文件名为 `package.json` 的文件生效。
262
+
263
+ `tsconfig.json` 排序支持 `json` 解析器,文件名必须是 `tsconfig.json` 或 `tsconfig.*.json`。
206
264
 
207
265
  ## TypeScript 配置
208
266
 
209
- 插件同时导出 `SortOptions`、`ImportGroup` 和 `TypeImportStyle`,可用于 TypeScript 配置文件:
267
+ 插件还导出 `SortOptions`、`ImportGroup` 和 `TypeImportStyle` 类型,可直接用于 TypeScript 配置文件:
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
  ```
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { type Plugin } from 'prettier';
2
2
  declare const sortPlugin: Plugin;
3
3
  export default sortPlugin;
4
- export { options } from './options';
5
- export type { ImportGroup, SortOptions, TypeImportStyle } from './options';
4
+ export { options } from '#/options';
5
+ export type { ImportGroup, SortOptions, TypeImportStyle } from '#/options';