@1adybug/prettier-plugin-sort-imports 0.0.26 → 0.0.28
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 +23 -5
- package/README.zh-CN.md +23 -5
- package/dist/index.d.ts +6 -0
- package/dist/index.js +67 -14
- package/dist/sorter.d.ts +2 -1
- package/dist/types.d.ts +2 -0
- package/package.json +9 -9
package/README.md
CHANGED
|
@@ -152,6 +152,8 @@ interface PluginConfig {
|
|
|
152
152
|
sortSideEffect?: boolean
|
|
153
153
|
/** Whether to remove unused imports, defaults to false */
|
|
154
154
|
removeUnusedImports?: boolean
|
|
155
|
+
/** Whether to add/remove the node: prefix for Node.js builtin modules */
|
|
156
|
+
nodeProtocol?: boolean
|
|
155
157
|
}
|
|
156
158
|
```
|
|
157
159
|
|
|
@@ -167,6 +169,7 @@ export default {
|
|
|
167
169
|
sortSideEffect: false, // Whether to sort side effect imports
|
|
168
170
|
groupSeparator: "", // Group separator
|
|
169
171
|
removeUnusedImports: false, // Whether to remove unused imports
|
|
172
|
+
nodeProtocol: true, // Add node: prefix for Node.js builtin modules (false to remove)
|
|
170
173
|
}
|
|
171
174
|
```
|
|
172
175
|
|
|
@@ -198,6 +201,7 @@ export default {
|
|
|
198
201
|
groupSeparator: "\n",
|
|
199
202
|
sortSideEffect: true,
|
|
200
203
|
removeUnusedImports: false,
|
|
204
|
+
nodeProtocol: true,
|
|
201
205
|
}),
|
|
202
206
|
],
|
|
203
207
|
}
|
|
@@ -347,7 +351,8 @@ Whether to remove unused imports, defaults to `false`.
|
|
|
347
351
|
|
|
348
352
|
```tsx
|
|
349
353
|
// Before sorting
|
|
350
|
-
|
|
354
|
+
// After sorting (with removeUnusedImports enabled)
|
|
355
|
+
import React, { useState } from "react"
|
|
351
356
|
|
|
352
357
|
import { Button } from "antd"
|
|
353
358
|
|
|
@@ -356,10 +361,6 @@ function MyComponent() {
|
|
|
356
361
|
return <Button>Click me</Button>
|
|
357
362
|
}
|
|
358
363
|
|
|
359
|
-
// After sorting (with removeUnusedImports enabled)
|
|
360
|
-
import React, { useState } from "react"
|
|
361
|
-
import { Button } from "antd"
|
|
362
|
-
|
|
363
364
|
function MyComponent() {
|
|
364
365
|
const [count, setCount] = useState(0)
|
|
365
366
|
return <Button>Click me</Button>
|
|
@@ -373,6 +374,23 @@ function MyComponent() {
|
|
|
373
374
|
- Analysis is AST-based and identifies actually used identifiers in code
|
|
374
375
|
- Supports identifying JSX components, TypeScript type references, etc.
|
|
375
376
|
|
|
377
|
+
### nodeProtocol
|
|
378
|
+
|
|
379
|
+
Whether to add/remove the `node:` prefix for Node.js builtin modules. Defaults to `undefined` (no change).
|
|
380
|
+
|
|
381
|
+
- `true`: add `node:` prefix
|
|
382
|
+
- `false`: remove `node:` prefix
|
|
383
|
+
|
|
384
|
+
```ts
|
|
385
|
+
// Before
|
|
386
|
+
// nodeProtocol: false
|
|
387
|
+
import fs from "fs"
|
|
388
|
+
// nodeProtocol: true
|
|
389
|
+
import fs from "node:fs"
|
|
390
|
+
import path from "node:path"
|
|
391
|
+
import path from "path"
|
|
392
|
+
```
|
|
393
|
+
|
|
376
394
|
### sortSideEffect
|
|
377
395
|
|
|
378
396
|
Whether to sort side effect imports, defaults to `false`.
|
package/README.zh-CN.md
CHANGED
|
@@ -151,6 +151,8 @@ interface PluginConfig {
|
|
|
151
151
|
sortSideEffect?: boolean
|
|
152
152
|
/** 是否删除未使用的导入,默认为 false */
|
|
153
153
|
removeUnusedImports?: boolean
|
|
154
|
+
/** 是否为 Node.js 内置模块自动添加/移除 node: 前缀 */
|
|
155
|
+
nodeProtocol?: boolean
|
|
154
156
|
}
|
|
155
157
|
```
|
|
156
158
|
|
|
@@ -166,6 +168,7 @@ export default {
|
|
|
166
168
|
sortSideEffect: false, // 是否对副作用导入排序
|
|
167
169
|
groupSeparator: "", // 分组分隔符
|
|
168
170
|
removeUnusedImports: false, // 是否删除未使用的导入
|
|
171
|
+
nodeProtocol: true, // 为 Node.js 内置模块添加 node: 前缀(false 为移除)
|
|
169
172
|
}
|
|
170
173
|
```
|
|
171
174
|
|
|
@@ -194,6 +197,7 @@ export default {
|
|
|
194
197
|
groupSeparator: "",
|
|
195
198
|
sortSideEffect: true,
|
|
196
199
|
removeUnusedImports: false,
|
|
200
|
+
nodeProtocol: true,
|
|
197
201
|
}),
|
|
198
202
|
],
|
|
199
203
|
}
|
|
@@ -343,7 +347,8 @@ export default {
|
|
|
343
347
|
|
|
344
348
|
```tsx
|
|
345
349
|
// 排序前
|
|
346
|
-
|
|
350
|
+
// 排序后(开启 removeUnusedImports)
|
|
351
|
+
import React, { useState } from "react"
|
|
347
352
|
|
|
348
353
|
import { Button } from "antd"
|
|
349
354
|
|
|
@@ -352,10 +357,6 @@ function MyComponent() {
|
|
|
352
357
|
return <Button>Click me</Button>
|
|
353
358
|
}
|
|
354
359
|
|
|
355
|
-
// 排序后(开启 removeUnusedImports)
|
|
356
|
-
import React, { useState } from "react"
|
|
357
|
-
import { Button } from "antd"
|
|
358
|
-
|
|
359
360
|
function MyComponent() {
|
|
360
361
|
const [count, setCount] = useState(0)
|
|
361
362
|
return <Button>Click me</Button>
|
|
@@ -369,6 +370,23 @@ function MyComponent() {
|
|
|
369
370
|
- 分析基于 AST,会识别代码中实际使用的标识符
|
|
370
371
|
- 支持识别 JSX 组件、TypeScript 类型引用等
|
|
371
372
|
|
|
373
|
+
### nodeProtocol
|
|
374
|
+
|
|
375
|
+
是否为 Node.js 内置模块自动添加/移除 `node:` 前缀,默认为 `undefined`(不处理)。
|
|
376
|
+
|
|
377
|
+
- `true`:自动添加 `node:` 前缀
|
|
378
|
+
- `false`:自动移除 `node:` 前缀
|
|
379
|
+
|
|
380
|
+
```ts
|
|
381
|
+
// 排序前
|
|
382
|
+
// nodeProtocol: false
|
|
383
|
+
import fs from "fs"
|
|
384
|
+
// nodeProtocol: true
|
|
385
|
+
import fs from "node:fs"
|
|
386
|
+
import path from "node:path"
|
|
387
|
+
import path from "path"
|
|
388
|
+
```
|
|
389
|
+
|
|
372
390
|
### sortSideEffect
|
|
373
391
|
|
|
374
392
|
是否对副作用导入进行排序,默认为 `false`。
|
package/dist/index.d.ts
CHANGED
|
@@ -17,6 +17,12 @@ export interface Options extends PrettierOptions {
|
|
|
17
17
|
* @default false
|
|
18
18
|
*/
|
|
19
19
|
removeUnusedImports?: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Whether to add/remove the node: prefix for Node.js builtin modules.
|
|
22
|
+
* true: add, false: remove, undefined: no change.
|
|
23
|
+
* @default undefined
|
|
24
|
+
*/
|
|
25
|
+
nodeProtocol?: boolean;
|
|
20
26
|
/**
|
|
21
27
|
* 自定义获取分组名称。
|
|
22
28
|
*/
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createRequire } from "module";
|
|
1
|
+
import { builtinModules, createRequire } from "module";
|
|
2
2
|
import { format } from "prettier";
|
|
3
3
|
import { parse as parser_parse } from "@babel/parser";
|
|
4
4
|
import traverse from "@babel/traverse";
|
|
@@ -209,7 +209,7 @@ function parseImports(code, filepath) {
|
|
|
209
209
|
const statement = parseImportNode(node, ast.comments ?? [], usedComments, code, isFirstImport, filepath);
|
|
210
210
|
importStatements.push(statement);
|
|
211
211
|
isFirstImport = false;
|
|
212
|
-
}
|
|
212
|
+
}
|
|
213
213
|
return importStatements;
|
|
214
214
|
}
|
|
215
215
|
function parseImportNode(node, comments, usedComments, code, isFirstImport, filepath) {
|
|
@@ -419,7 +419,8 @@ function mergeConfig(userConfig) {
|
|
|
419
419
|
sortImportContent: userConfig.sortImportContent ?? DEFAULT_CONFIG.sortImportContent,
|
|
420
420
|
groupSeparator: userConfig.groupSeparator,
|
|
421
421
|
sortSideEffect: userConfig.sortSideEffect ?? DEFAULT_CONFIG.sortSideEffect,
|
|
422
|
-
removeUnusedImports: userConfig.removeUnusedImports ?? false
|
|
422
|
+
removeUnusedImports: userConfig.removeUnusedImports ?? false,
|
|
423
|
+
nodeProtocol: userConfig.nodeProtocol
|
|
423
424
|
};
|
|
424
425
|
}
|
|
425
426
|
function sortImports(imports, userConfig) {
|
|
@@ -583,6 +584,51 @@ function mergeImports(imports) {
|
|
|
583
584
|
return Array.from(mergedMap.values());
|
|
584
585
|
}
|
|
585
586
|
const src_require = createRequire(import.meta.url);
|
|
587
|
+
const NODE_BUILTIN_MODULES = new Set(builtinModules.map((moduleName)=>moduleName.startsWith("node:") ? moduleName.slice(5) : moduleName));
|
|
588
|
+
function isNodeBuiltinModule(modulePath) {
|
|
589
|
+
const normalizedPath = modulePath.startsWith("node:") ? modulePath.slice(5) : modulePath;
|
|
590
|
+
if (NODE_BUILTIN_MODULES.has(normalizedPath)) return true;
|
|
591
|
+
const slashIndex = normalizedPath.indexOf("/");
|
|
592
|
+
if (-1 === slashIndex) return false;
|
|
593
|
+
return NODE_BUILTIN_MODULES.has(normalizedPath.slice(0, slashIndex));
|
|
594
|
+
}
|
|
595
|
+
function applyNodeProtocol(modulePath, nodeProtocol) {
|
|
596
|
+
if (void 0 === nodeProtocol) return modulePath;
|
|
597
|
+
const hasNodePrefix = modulePath.startsWith("node:");
|
|
598
|
+
const normalizedPath = hasNodePrefix ? modulePath.slice(5) : modulePath;
|
|
599
|
+
if (!isNodeBuiltinModule(normalizedPath)) return modulePath;
|
|
600
|
+
if (nodeProtocol) return hasNodePrefix ? modulePath : `node:${modulePath}`;
|
|
601
|
+
return hasNodePrefix ? normalizedPath : modulePath;
|
|
602
|
+
}
|
|
603
|
+
function getImportRanges(imports) {
|
|
604
|
+
const ranges = imports.map((statement)=>({
|
|
605
|
+
start: statement.start ?? 0,
|
|
606
|
+
end: statement.end ?? 0
|
|
607
|
+
})).filter((range)=>range.end > range.start).sort((a, b)=>a.start - b.start);
|
|
608
|
+
const merged = [];
|
|
609
|
+
for (const range of ranges){
|
|
610
|
+
const last = merged[merged.length - 1];
|
|
611
|
+
if (last && range.start <= last.end) {
|
|
612
|
+
last.end = Math.max(last.end, range.end);
|
|
613
|
+
continue;
|
|
614
|
+
}
|
|
615
|
+
merged.push({
|
|
616
|
+
...range
|
|
617
|
+
});
|
|
618
|
+
}
|
|
619
|
+
return merged;
|
|
620
|
+
}
|
|
621
|
+
function removeRangesFromText(text, ranges) {
|
|
622
|
+
if (0 === ranges.length) return text;
|
|
623
|
+
let result = "";
|
|
624
|
+
let cursor = 0;
|
|
625
|
+
for (const range of ranges){
|
|
626
|
+
result += text.slice(cursor, range.start);
|
|
627
|
+
cursor = range.end;
|
|
628
|
+
}
|
|
629
|
+
result += text.slice(cursor);
|
|
630
|
+
return result;
|
|
631
|
+
}
|
|
586
632
|
function preprocessImports(text, options, config = {}) {
|
|
587
633
|
try {
|
|
588
634
|
const parser = options.parser;
|
|
@@ -603,14 +649,17 @@ function preprocessImports(text, options, config = {}) {
|
|
|
603
649
|
sortImportContent: config.sortImportContent ?? optionsConfig.sortImportContent,
|
|
604
650
|
groupSeparator: config.groupSeparator ?? optionsConfig.groupSeparator,
|
|
605
651
|
sortSideEffect: config.sortSideEffect ?? optionsConfig.sortSideEffect ?? false,
|
|
606
|
-
removeUnusedImports: config.removeUnusedImports ?? optionsConfig.removeUnusedImports ?? false
|
|
652
|
+
removeUnusedImports: config.removeUnusedImports ?? optionsConfig.removeUnusedImports ?? false,
|
|
653
|
+
nodeProtocol: config.nodeProtocol ?? optionsConfig.nodeProtocol
|
|
607
654
|
};
|
|
655
|
+
const importRanges = getImportRanges(imports);
|
|
656
|
+
const textWithoutImports = removeRangesFromText(text, importRanges);
|
|
608
657
|
let processedImports = imports;
|
|
609
|
-
if (finalConfig.removeUnusedImports)
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
658
|
+
if (finalConfig.removeUnusedImports) processedImports = removeUnusedImportsFromStatements(imports, textWithoutImports);
|
|
659
|
+
if (void 0 !== finalConfig.nodeProtocol) processedImports = processedImports.map((statement)=>({
|
|
660
|
+
...statement,
|
|
661
|
+
path: applyNodeProtocol(statement.path, finalConfig.nodeProtocol)
|
|
662
|
+
}));
|
|
614
663
|
const sortedImports = sortImports(processedImports, finalConfig);
|
|
615
664
|
const mergedImports = mergeImports(sortedImports);
|
|
616
665
|
let formattedImports;
|
|
@@ -620,13 +669,12 @@ function preprocessImports(text, options, config = {}) {
|
|
|
620
669
|
formattedImports = formatGroups(sortedGroups, finalConfig, options.trailingComma);
|
|
621
670
|
} else formattedImports = formatImportStatements(mergedImports, options.trailingComma);
|
|
622
671
|
const firstImport = imports[0];
|
|
623
|
-
const lastImport = imports[imports.length - 1];
|
|
624
672
|
const startIndex = firstImport.start ?? 0;
|
|
625
|
-
const
|
|
626
|
-
|
|
627
|
-
|
|
673
|
+
const beforeImports = textWithoutImports.slice(0, startIndex);
|
|
674
|
+
let afterImports = textWithoutImports.slice(startIndex);
|
|
675
|
+
if (afterImports) afterImports = afterImports.replace(/^\n+/, "\n");
|
|
628
676
|
const needsExtraNewline = afterImports && !afterImports.startsWith("\n");
|
|
629
|
-
const separator = needsExtraNewline ? "\n\n" : "\n";
|
|
677
|
+
const separator = afterImports ? needsExtraNewline ? "\n\n" : "\n" : "";
|
|
630
678
|
return beforeImports + formattedImports + separator + afterImports;
|
|
631
679
|
} catch (error) {
|
|
632
680
|
return text;
|
|
@@ -676,6 +724,11 @@ function createPluginInstance(config = {}) {
|
|
|
676
724
|
category: "Import Sort",
|
|
677
725
|
description: "�Ƿ�ɾ��δʹ�õĵ���",
|
|
678
726
|
default: false
|
|
727
|
+
},
|
|
728
|
+
nodeProtocol: {
|
|
729
|
+
type: "boolean",
|
|
730
|
+
category: "Import Sort",
|
|
731
|
+
description: "Use node: prefix for Node.js builtin modules"
|
|
679
732
|
}
|
|
680
733
|
};
|
|
681
734
|
const otherPlugins = config.otherPlugins || [];
|
package/dist/sorter.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { Group, ImportContent, ImportStatement, PluginConfig } from "./types";
|
|
2
2
|
/** 合并后的配置 */
|
|
3
|
-
export interface MergedConfig extends Omit<Required<PluginConfig>, "groupSeparator" | "removeUnusedImports" | "otherPlugins" | "prettierOptions"> {
|
|
3
|
+
export interface MergedConfig extends Omit<Required<PluginConfig>, "groupSeparator" | "removeUnusedImports" | "nodeProtocol" | "otherPlugins" | "prettierOptions"> {
|
|
4
4
|
groupSeparator: PluginConfig["groupSeparator"];
|
|
5
5
|
removeUnusedImports: boolean;
|
|
6
|
+
nodeProtocol?: boolean;
|
|
6
7
|
}
|
|
7
8
|
/** 对导入语句进行排序 */
|
|
8
9
|
export declare function sortImports(imports: ImportStatement[], userConfig: PluginConfig): ImportStatement[];
|
package/dist/types.d.ts
CHANGED
|
@@ -76,6 +76,8 @@ export interface PluginConfig {
|
|
|
76
76
|
sortSideEffect?: boolean;
|
|
77
77
|
/** 是否删除未使用的导入,默认为 false */
|
|
78
78
|
removeUnusedImports?: boolean;
|
|
79
|
+
/** Whether to add/remove the node: prefix for Node.js builtin modules */
|
|
80
|
+
nodeProtocol?: boolean;
|
|
79
81
|
/** 要合并的其他 Prettier 插件,按传入顺序执行 */
|
|
80
82
|
otherPlugins?: Plugin[];
|
|
81
83
|
/** 传递给其他插件的 Prettier 配置选项 */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@1adybug/prettier-plugin-sort-imports",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.28",
|
|
4
4
|
"description": "一个 Prettier 插件,用于对 JavaScript/TypeScript 文件的导入语句进行分组和排序",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"prettier",
|
|
@@ -41,23 +41,23 @@
|
|
|
41
41
|
"registry": "https://registry.npmjs.com/"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@babel/core": "^7.28.
|
|
45
|
-
"@babel/parser": "^7.28.
|
|
46
|
-
"@babel/traverse": "^7.28.
|
|
47
|
-
"@babel/types": "^7.28.
|
|
44
|
+
"@babel/core": "^7.28.6",
|
|
45
|
+
"@babel/parser": "^7.28.6",
|
|
46
|
+
"@babel/traverse": "^7.28.6",
|
|
47
|
+
"@babel/types": "^7.28.6"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
|
-
"@rslib/core": "^0.15.
|
|
50
|
+
"@rslib/core": "^0.15.1",
|
|
51
51
|
"@types/babel__core": "^7.20.5",
|
|
52
52
|
"@types/babel__traverse": "^7.28.0",
|
|
53
53
|
"@types/bun": "latest",
|
|
54
|
-
"@types/node": "^
|
|
54
|
+
"@types/node": "^24.10.8",
|
|
55
55
|
"json5": "^2.2.3",
|
|
56
56
|
"supports-color": "^10.2.2",
|
|
57
|
-
"typescript": "^5.9.
|
|
57
|
+
"typescript": "^5.9.3"
|
|
58
58
|
},
|
|
59
59
|
"peerDependencies": {
|
|
60
|
-
"prettier": "^3.
|
|
60
|
+
"prettier": "^3.8.0"
|
|
61
61
|
},
|
|
62
62
|
"scripts": {
|
|
63
63
|
"build": "rslib build",
|