@1adybug/prettier-plugin-sort-imports 0.0.5 → 0.0.7

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
@@ -13,13 +13,14 @@ A powerful Prettier plugin for intelligently grouping and sorting import stateme
13
13
  - ✅ **Side Effect Handling**: Configurable sorting behavior for side effect imports
14
14
  - ✅ **Unused Import Removal**: Optional automatic removal of unused imports
15
15
  - ✅ **Factory Function Pattern**: Support for custom functions in configuration files
16
+ - ✅ **Tailwind CSS Integration**: Compatible with `prettier-plugin-tailwindcss`
16
17
 
17
18
  ## Quick Start
18
19
 
19
20
  ### Installation
20
21
 
21
22
  ```bash
22
- npm install prettier-plugin-import-sorts --save-dev
23
+ npm install @1adybug/prettier-plugin-sort-imports --save-dev
23
24
  ```
24
25
 
25
26
  ### Basic Configuration
@@ -28,7 +29,7 @@ Add the plugin to your `prettier.config.mjs`:
28
29
 
29
30
  ```javascript
30
31
  export default {
31
- plugins: ["prettier-plugin-import-sorts"],
32
+ plugins: ["@1adybug/prettier-plugin-sort-imports"],
32
33
  }
33
34
  ```
34
35
 
@@ -50,7 +51,7 @@ npx prettier --write "src/**/*.{js,ts,jsx,tsx}"
50
51
 
51
52
  ```javascript
52
53
  // prettier.config.mjs
53
- import { createPlugin } from "prettier-plugin-import-sorts"
54
+ import { createPlugin } from "@1adybug/prettier-plugin-sort-imports"
54
55
 
55
56
  export default {
56
57
  plugins: [
@@ -157,40 +158,46 @@ interface PluginConfig {
157
158
 
158
159
  ### Method 1: Simple Configuration
159
160
 
160
- Configure basic options via Prettier config file:
161
+ Use the default plugin with basic options:
161
162
 
162
163
  ```javascript
163
164
  export default {
164
- plugins: ["prettier-plugin-import-sorts"],
165
+ plugins: ["@1adybug/prettier-plugin-sort-imports"],
165
166
  importSortSideEffect: false, // Whether to sort side effect imports
166
167
  importSortSeparator: "", // Group separator
167
168
  importSortRemoveUnused: false, // Whether to remove unused imports
168
169
  }
169
170
  ```
170
171
 
171
- ### Method 2: Advanced Configuration (Factory Function)
172
+ ### Method 2: Advanced Configuration
172
173
 
173
- Use `createPlugin` function to pass custom functions:
174
+ Use `createPlugin` function for full control and plugin compatibility:
174
175
 
175
176
  ```javascript
176
- import { createPlugin } from "prettier-plugin-import-sorts"
177
+ import { createPlugin } from "@1adybug/prettier-plugin-sort-imports"
177
178
 
178
179
  export default {
179
180
  plugins: [
180
181
  createPlugin({
182
+ // Custom sorting functions
181
183
  getGroup: statement => {
182
- /* Custom grouping logic */
184
+ if (statement.path.startsWith("react")) return "react"
185
+ if (!statement.path.startsWith(".")) return "external"
186
+ return "local"
183
187
  },
184
188
  sortGroup: (a, b) => {
185
- /* Custom sorting */
189
+ const order = ["react", "external", "local"]
190
+ return order.indexOf(a.name) - order.indexOf(b.name)
186
191
  },
187
192
  sortImportStatement: (a, b) => {
188
- /* Custom sorting */
193
+ return a.path.localeCompare(b.path)
189
194
  },
190
195
  sortImportContent: (a, b) => {
191
- /* Custom sorting */
196
+ return a.name.localeCompare(b.name)
192
197
  },
193
- separator: "",
198
+
199
+ // Configuration
200
+ separator: "\n",
194
201
  sortSideEffect: true,
195
202
  removeUnusedImports: false,
196
203
  }),
@@ -198,42 +205,150 @@ export default {
198
205
  }
199
206
  ```
200
207
 
201
- ### Method 3: Config File Path
208
+ ### Method 3: Custom Plugin Module
202
209
 
203
- Use `sortImportsConfigPath` option to load configuration from an external file:
210
+ Create a custom plugin module for better organization and reusability:
204
211
 
205
- ```javascript
206
- // prettier.config.mjs
207
- export default {
208
- plugins: ["prettier-plugin-import-sorts"],
209
- sortImportsConfigPath: "./import-sort.config.js",
210
- }
211
- ```
212
+ **Step 1**: Create a custom plugin file `prettier-plugin-sort-imports.mjs`:
212
213
 
213
214
  ```javascript
214
- // import-sort.config.js (or import-sort.config.cjs)
215
- module.exports = {
216
- getGroup: importStatement => {
217
- const path = importStatement.path
218
- if (path.startsWith("react")) return "react"
219
- if (path.startsWith("@/")) return "internal"
220
- if (path.startsWith(".")) return "relative"
221
- return "external"
215
+ // prettier-plugin-sort-imports.mjs
216
+ import { createPlugin } from "@1adybug/prettier-plugin-sort-imports"
217
+
218
+ export default createPlugin({
219
+ // Custom grouping logic
220
+ getGroup: statement => {
221
+ const path = statement.path
222
+
223
+ // React and related libraries
224
+ if (path.startsWith("react") || path.startsWith("@react")) {
225
+ return "react"
226
+ }
227
+
228
+ // UI libraries
229
+ if (path.includes("antd") || path.includes("@mui") || path.includes("chakra")) {
230
+ return "ui"
231
+ }
232
+
233
+ // Utility libraries
234
+ if (path.includes("lodash") || path.includes("ramda") || path.includes("date-fns")) {
235
+ return "utils"
236
+ }
237
+
238
+ // External packages (node_modules)
239
+ if (!path.startsWith(".") && !path.startsWith("@/")) {
240
+ return "external"
241
+ }
242
+
243
+ // Internal aliases (@/)
244
+ if (path.startsWith("@/")) {
245
+ return "internal"
246
+ }
247
+
248
+ // Relative imports
249
+ return "relative"
222
250
  },
251
+
252
+ // Define group order
223
253
  sortGroup: (a, b) => {
224
- const order = ["react", "external", "internal", "relative"]
254
+ const order = ["react", "external", "ui", "utils", "internal", "relative"]
225
255
  return order.indexOf(a.name) - order.indexOf(b.name)
226
256
  },
257
+
258
+ // Custom import content sorting
259
+ sortImportContent: (a, b) => {
260
+ // Types first, then variables
261
+ if (a.type !== b.type) {
262
+ return a.type === "type" ? -1 : 1
263
+ }
264
+
265
+ // Alphabetical order within same type
266
+ const aName = a.alias ?? a.name
267
+ const bName = b.alias ?? b.name
268
+ return aName.localeCompare(bName)
269
+ },
270
+
271
+ // Add blank lines between groups
227
272
  separator: "\n",
273
+
274
+ // Sort side effects
275
+ sortSideEffect: true,
276
+ })
277
+ ```
278
+
279
+ **Step 2**: Use the custom plugin in your `prettier.config.mjs`:
280
+
281
+ ```javascript
282
+ // prettier.config.mjs
283
+ export default {
284
+ plugins: ["./prettier-plugin-sort-imports.mjs"],
285
+ // Other prettier options...
286
+ semi: false,
287
+ tabWidth: 4,
228
288
  }
229
289
  ```
230
290
 
231
- **Important Notes**:
291
+ **Benefits of this approach**:
292
+
293
+ - ✅ **Reusable**: Share the same configuration across multiple projects
294
+ - ✅ **Version Control**: Track your import sorting rules in git
295
+ - ✅ **Maintainable**: Keep complex logic separate from prettier config
296
+ - ✅ **Team Collaboration**: Consistent import sorting rules across team members
232
297
 
233
- - Config file must use **CommonJS format** (`module.exports`), ESM format (`export default`) is not supported
234
- - If your project has `"type": "module"` in `package.json`, use `.cjs` extension (e.g., `import-sort.config.cjs`)
235
- - Config file path is resolved relative to the project root (`process.cwd()`)
236
- - Configuration priority: `createPlugin` parameters > `sortImportsConfigPath` loaded config > Prettier config options
298
+ ### Method 4: Plugin Compatibility
299
+
300
+ Use `createPlugin` with `otherPlugins` to merge with other Prettier plugins and avoid conflicts:
301
+
302
+ ```javascript
303
+ import { createPlugin } from "@1adybug/prettier-plugin-sort-imports"
304
+ import * as tailwindPlugin from "prettier-plugin-tailwindcss"
305
+
306
+ export default {
307
+ plugins: [
308
+ createPlugin({
309
+ // Your import sorting configuration
310
+ getGroup: statement => {
311
+ if (statement.path.startsWith("react")) return "react"
312
+ if (!statement.path.startsWith(".")) return "external"
313
+ return "local"
314
+ },
315
+ separator: "\n",
316
+
317
+ // Other Prettier plugins to combine with (Plugin objects only)
318
+ otherPlugins: [
319
+ tailwindPlugin, // Import the plugin directly
320
+ // Add more plugins as needed...
321
+ ],
322
+
323
+ // Configuration options for other plugins
324
+ prettierOptions: {
325
+ // TailwindCSS plugin options
326
+ tailwindConfig: "./tailwind.config.js",
327
+ tailwindFunctions: ["clsx", "cn", "cva"],
328
+ tailwindAttributes: ["class", "className", "ngClass", ":class"],
329
+
330
+ // Other plugin options can go here...
331
+ },
332
+ }),
333
+ ],
334
+ }
335
+ ```
336
+
337
+ **Important Notes:**
338
+
339
+ - `otherPlugins` only accepts imported Plugin objects, not string plugin names
340
+ - You must import the plugins yourself to ensure proper module resolution
341
+ - This approach avoids complex module loading issues and gives you full control
342
+
343
+ **Plugin Execution Order:**
344
+
345
+ - Other plugins are executed in the order they appear in the `otherPlugins` array
346
+ - Import sorting is always executed last to ensure compatibility
347
+
348
+ **Configuration Passing:**
349
+
350
+ - Options in `prettierOptions` are passed to all other plugins
351
+ - This allows other plugins to receive their configuration even when merged
237
352
 
238
353
  ### importSortRemoveUnused
239
354
 
@@ -427,7 +542,7 @@ Prettier natively cannot accept functions as configuration parameters (because c
427
542
 
428
543
  ```javascript
429
544
  // Factory function is called in config file, returning a plugin instance
430
- import { createPlugin } from "prettier-plugin-import-sorts"
545
+ import { createPlugin } from "@1adybug/prettier-plugin-sort-imports"
431
546
 
432
547
  export default {
433
548
  plugins: [
@@ -443,6 +558,30 @@ export default {
443
558
 
444
559
  This maintains configuration flexibility while not violating Prettier's configuration system limitations.
445
560
 
561
+ ## Integration with Other Plugins
562
+
563
+ ### Tailwind CSS
564
+
565
+ This plugin works seamlessly with `prettier-plugin-tailwindcss`. For detailed setup instructions, see [TAILWINDCSS_INTEGRATION.md](./TAILWINDCSS_INTEGRATION.md).
566
+
567
+ **Quick Setup:**
568
+
569
+ ```javascript
570
+ // prettier.config.mjs
571
+ export default {
572
+ plugins: [
573
+ "@1adybug/prettier-plugin-sort-imports",
574
+ "prettier-plugin-tailwindcss", // Must come last
575
+ ],
576
+ tailwindFunctions: ["clsx", "cn", "cva", "tw"],
577
+ }
578
+ ```
579
+
580
+ This will:
581
+
582
+ - ✅ Sort and merge your imports
583
+ - ✅ Sort your Tailwind CSS classes according to the recommended order
584
+
446
585
  ## Notes
447
586
 
448
587
  1. **Only processes consecutive import/export statement blocks at the beginning of files**
package/README.zh-CN.md CHANGED
@@ -19,7 +19,7 @@
19
19
  ### 安装
20
20
 
21
21
  ```bash
22
- npm install prettier-plugin-import-sorts --save-dev
22
+ npm install @1adybug/prettier-plugin-sort-imports --save-dev
23
23
  ```
24
24
 
25
25
  ### 基础配置
@@ -28,7 +28,7 @@ npm install prettier-plugin-import-sorts --save-dev
28
28
 
29
29
  ```javascript
30
30
  export default {
31
- plugins: ["prettier-plugin-import-sorts"],
31
+ plugins: ["@1adybug/prettier-plugin-sort-imports"],
32
32
  }
33
33
  ```
34
34
 
@@ -50,7 +50,7 @@ npx prettier --write "src/**/*.{js,ts,jsx,tsx}"
50
50
 
51
51
  ```javascript
52
52
  // prettier.config.mjs
53
- import { createPlugin } from "prettier-plugin-import-sorts"
53
+ import { createPlugin } from "@1adybug/prettier-plugin-sort-imports"
54
54
 
55
55
  export default {
56
56
  plugins: [
@@ -161,7 +161,7 @@ interface PluginConfig {
161
161
 
162
162
  ```javascript
163
163
  export default {
164
- plugins: ["prettier-plugin-import-sorts"],
164
+ plugins: ["@1adybug/prettier-plugin-sort-imports"],
165
165
  importSortSideEffect: false, // 是否对副作用导入排序
166
166
  importSortSeparator: "", // 分组分隔符
167
167
  importSortRemoveUnused: false, // 是否删除未使用的导入
@@ -173,7 +173,7 @@ export default {
173
173
  使用 `createPlugin` 函数可以传递自定义函数:
174
174
 
175
175
  ```javascript
176
- import { createPlugin } from "prettier-plugin-import-sorts"
176
+ import { createPlugin } from "@1adybug/prettier-plugin-sort-imports"
177
177
 
178
178
  export default {
179
179
  plugins: [
@@ -198,42 +198,150 @@ export default {
198
198
  }
199
199
  ```
200
200
 
201
- ### 方式 3:配置文件路径
201
+ ### 方式 3:自定义插件模块
202
202
 
203
- 使用 `sortImportsConfigPath` 选项从外部文件加载配置:
203
+ 创建自定义插件模块以获得更好的组织性和可复用性:
204
204
 
205
- ```javascript
206
- // prettier.config.mjs
207
- export default {
208
- plugins: ["prettier-plugin-import-sorts"],
209
- sortImportsConfigPath: "./import-sort.config.js",
210
- }
211
- ```
205
+ **步骤 1**:创建自定义插件文件 `prettier-plugin-sort-imports.mjs`:
212
206
 
213
207
  ```javascript
214
- // import-sort.config.js (或 import-sort.config.cjs)
215
- module.exports = {
216
- getGroup: importStatement => {
217
- const path = importStatement.path
218
- if (path.startsWith("react")) return "react"
219
- if (path.startsWith("@/")) return "internal"
220
- if (path.startsWith(".")) return "relative"
221
- return "external"
208
+ // prettier-plugin-sort-imports.mjs
209
+ import { createPlugin } from "@1adybug/prettier-plugin-sort-imports"
210
+
211
+ export default createPlugin({
212
+ // 自定义分组逻辑
213
+ getGroup: statement => {
214
+ const path = statement.path
215
+
216
+ // React 及相关库
217
+ if (path.startsWith("react") || path.startsWith("@react")) {
218
+ return "react"
219
+ }
220
+
221
+ // UI 库
222
+ if (path.includes("antd") || path.includes("@mui") || path.includes("chakra")) {
223
+ return "ui"
224
+ }
225
+
226
+ // 工具库
227
+ if (path.includes("lodash") || path.includes("ramda") || path.includes("date-fns")) {
228
+ return "utils"
229
+ }
230
+
231
+ // 外部包 (node_modules)
232
+ if (!path.startsWith(".") && !path.startsWith("@/")) {
233
+ return "external"
234
+ }
235
+
236
+ // 内部别名 (@/)
237
+ if (path.startsWith("@/")) {
238
+ return "internal"
239
+ }
240
+
241
+ // 相对导入
242
+ return "relative"
222
243
  },
244
+
245
+ // 定义分组顺序
223
246
  sortGroup: (a, b) => {
224
- const order = ["react", "external", "internal", "relative"]
247
+ const order = ["react", "external", "ui", "utils", "internal", "relative"]
225
248
  return order.indexOf(a.name) - order.indexOf(b.name)
226
249
  },
250
+
251
+ // 自定义导入内容排序
252
+ sortImportContent: (a, b) => {
253
+ // 类型在前,变量在后
254
+ if (a.type !== b.type) {
255
+ return a.type === "type" ? -1 : 1
256
+ }
257
+
258
+ // 同类型内按字母顺序
259
+ const aName = a.alias ?? a.name
260
+ const bName = b.alias ?? b.name
261
+ return aName.localeCompare(bName)
262
+ },
263
+
264
+ // 在分组间添加空行
227
265
  separator: "\n",
266
+
267
+ // 排序副作用导入
268
+ sortSideEffect: true,
269
+ })
270
+ ```
271
+
272
+ **步骤 2**:在 `prettier.config.mjs` 中使用自定义插件:
273
+
274
+ ```javascript
275
+ // prettier.config.mjs
276
+ export default {
277
+ plugins: ["./prettier-plugin-sort-imports.mjs"],
278
+ // 其他 prettier 选项...
279
+ semi: false,
280
+ tabWidth: 4,
281
+ }
282
+ ```
283
+
284
+ **此方法的优点**:
285
+
286
+ - ✅ **可复用**:在多个项目间共享相同配置
287
+ - ✅ **版本控制**:在 git 中跟踪你的导入排序规则
288
+ - ✅ **易维护**:将复杂逻辑从 prettier 配置中分离
289
+ - ✅ **团队协作**:团队成员间保持一致的导入排序规则
290
+
291
+ ### 方式 4:插件兼容性
292
+
293
+ 使用 `createPlugin` 的 `otherPlugins` 参数与其他 Prettier 插件合并,避免冲突:
294
+
295
+ ```javascript
296
+ import { createPlugin } from "@1adybug/prettier-plugin-sort-imports"
297
+ import * as tailwindPlugin from "prettier-plugin-tailwindcss"
298
+
299
+ export default {
300
+ plugins: [
301
+ createPlugin({
302
+ // 你的导入排序配置
303
+ getGroup: statement => {
304
+ if (statement.path.startsWith("react")) return "react"
305
+ if (!statement.path.startsWith(".")) return "external"
306
+ return "local"
307
+ },
308
+ separator: "\n",
309
+
310
+ // 要合并的其他 Prettier 插件(仅支持 Plugin 对象)
311
+ otherPlugins: [
312
+ tailwindPlugin, // 直接导入插件
313
+ // 根据需要添加更多插件...
314
+ ],
315
+
316
+ // 其他插件的配置选项
317
+ prettierOptions: {
318
+ // TailwindCSS 插件选项
319
+ tailwindConfig: "./tailwind.config.js",
320
+ tailwindFunctions: ["clsx", "cn", "cva"],
321
+ tailwindAttributes: ["class", "className", "ngClass", ":class"],
322
+
323
+ // 其他插件选项可以在这里配置...
324
+ },
325
+ }),
326
+ ],
228
327
  }
229
328
  ```
230
329
 
231
- **重要提示**:
330
+ **重要说明**:
331
+
332
+ - `otherPlugins` 只接受导入的 Plugin 对象,不支持字符串插件名称
333
+ - 你必须自己导入插件以确保正确的模块解析
334
+ - 这种方法避免了复杂的模块加载问题,给你完全的控制权
335
+
336
+ **插件执行顺序**:
337
+
338
+ - 其他插件按照在 `otherPlugins` 数组中出现的顺序执行
339
+ - 导入排序始终最后执行以确保兼容性
340
+
341
+ **配置传递**:
232
342
 
233
- - 配置文件必须使用 **CommonJS 格式**(`module.exports`),不支持 ESM 格式(`export default`)
234
- - 如果你的项目在 `package.json` 中设置了 `"type": "module"`,请使用 `.cjs` 扩展名(如 `import-sort.config.cjs`)
235
- - 配置文件路径相对于项目根目录(`process.cwd()`)解析
236
- - 配置优先级:`createPlugin` 参数 > `sortImportsConfigPath` 加载的配置 > Prettier 配置选项
343
+ - `prettierOptions` 中的选项会传递给所有其他插件
344
+ - 这允许其他插件即使在合并时也能接收到它们的配置
237
345
 
238
346
  ### importSortRemoveUnused
239
347
 
@@ -427,7 +535,7 @@ Prettier 原生无法接受函数作为配置参数(因为配置需要序列
427
535
 
428
536
  ```javascript
429
537
  // 工厂函数在配置文件中被调用,返回一个插件实例
430
- import { createPlugin } from "prettier-plugin-import-sorts"
538
+ import { createPlugin } from "@1adybug/prettier-plugin-sort-imports"
431
539
 
432
540
  export default {
433
541
  plugins: [
package/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { Plugin } from "prettier";
2
- import { PluginConfig } from "./types";
2
+ import type { PluginConfig } from "./types";
3
3
  export * from "./types";
4
- /** 默认插件实例(用于简单使用) */
5
- declare const plugin: Plugin;
6
4
  /** 创建自定义配置的插件(工厂函数) */
7
5
  export declare function createPlugin(config?: PluginConfig): Plugin;
6
+ /** 默认插件实例(用于简单使用) */
7
+ declare const plugin: Plugin;
8
8
  export default plugin;
package/dist/index.js CHANGED
@@ -1,5 +1,4 @@
1
1
  import { createRequire } from "module";
2
- import { resolve } from "path";
3
2
  import { parse } from "@babel/parser";
4
3
  import traverse from "@babel/traverse";
5
4
  function analyzeUsedIdentifiers(code) {
@@ -236,7 +235,8 @@ function parseImportNode(node, comments, usedComments) {
236
235
  start,
237
236
  end
238
237
  };
239
- const importContents = parseExportSpecifiers(node);
238
+ const isTypeOnlyExport = "type" === node.exportKind;
239
+ const importContents = parseExportSpecifiers(node, isTypeOnlyExport);
240
240
  return {
241
241
  path: source,
242
242
  isExport: true,
@@ -290,7 +290,7 @@ function parseImportSpecifiers(node, isTypeOnlyImport = false) {
290
290
  }
291
291
  return contents;
292
292
  }
293
- function parseExportSpecifiers(node) {
293
+ function parseExportSpecifiers(node, isTypeOnlyExport = false) {
294
294
  const contents = [];
295
295
  if (!node.specifiers) return contents;
296
296
  for (const specifier of node.specifiers)if ("ExportSpecifier" === specifier.type) {
@@ -306,7 +306,7 @@ function parseExportSpecifiers(node) {
306
306
  }
307
307
  const localName = "Identifier" === specifier.local.type ? specifier.local.name : specifier.local.value;
308
308
  const exportedName = "Identifier" === specifier.exported.type ? specifier.exported.name : specifier.exported.value;
309
- const isTypeExport = "type" === specifier.exportKind;
309
+ const isTypeExport = isTypeOnlyExport || "type" === specifier.exportKind;
310
310
  contents.push({
311
311
  name: localName,
312
312
  alias: localName !== exportedName ? exportedName : void 0,
@@ -526,58 +526,33 @@ function mergeImports(imports) {
526
526
  return Array.from(mergedMap.values());
527
527
  }
528
528
  const src_require = createRequire(import.meta.url);
529
- let src_userConfig = {};
530
- const configCache = new Map();
531
- function loadConfigFromPath(configPath) {
532
- if (configCache.has(configPath)) return configCache.get(configPath);
533
- try {
534
- const absolutePath = resolve(process.cwd(), configPath);
535
- let config = {};
536
- try {
537
- delete src_require.cache[absolutePath];
538
- const module = src_require(absolutePath);
539
- config = module.default || module || {};
540
- } catch (requireError) {
541
- throw new Error(`Failed to load config file: ${configPath}. Please ensure the config file uses CommonJS format (module.exports) or has a .cjs extension. ESM format (.mjs or "type": "module") is not supported in synchronous loading context.\nOriginal error: ${requireError}`);
542
- }
543
- configCache.set(configPath, config);
544
- return config;
545
- } catch (error) {
546
- console.error(`Failed to load config from ${configPath}:`, error);
547
- const emptyConfig = {};
548
- configCache.set(configPath, emptyConfig);
549
- return emptyConfig;
550
- }
551
- }
552
- function preprocessImports(text, options) {
529
+ function preprocessImports(text, options, config = {}) {
553
530
  try {
554
531
  const imports = parseImports(text);
555
532
  if (0 === imports.length) return text;
556
- const configPath = options.sortImportsConfigPath;
557
- let fileConfig = {};
558
- if (configPath && "string" == typeof configPath) fileConfig = loadConfigFromPath(configPath);
559
- const config = {
560
- getGroup: src_userConfig.getGroup ?? fileConfig.getGroup ?? options.getGroup,
561
- sortGroup: src_userConfig.sortGroup ?? fileConfig.sortGroup ?? options.sortGroup,
562
- sortImportStatement: src_userConfig.sortImportStatement ?? fileConfig.sortImportStatement ?? options.sortImportStatement,
563
- sortImportContent: src_userConfig.sortImportContent ?? fileConfig.sortImportContent ?? options.sortImportContent,
564
- separator: src_userConfig.separator ?? fileConfig.separator ?? options.importSortSeparator ?? options.separator,
565
- sortSideEffect: src_userConfig.sortSideEffect ?? fileConfig.sortSideEffect ?? options.importSortSideEffect ?? false,
566
- removeUnusedImports: src_userConfig.removeUnusedImports ?? fileConfig.removeUnusedImports ?? options.importSortRemoveUnused ?? false
533
+ const optionsConfig = options;
534
+ const finalConfig = {
535
+ getGroup: config.getGroup ?? optionsConfig.getGroup,
536
+ sortGroup: config.sortGroup ?? optionsConfig.sortGroup,
537
+ sortImportStatement: config.sortImportStatement ?? optionsConfig.sortImportStatement,
538
+ sortImportContent: config.sortImportContent ?? optionsConfig.sortImportContent,
539
+ separator: config.separator ?? optionsConfig.importSortSeparator ?? optionsConfig.separator,
540
+ sortSideEffect: config.sortSideEffect ?? optionsConfig.importSortSideEffect ?? false,
541
+ removeUnusedImports: config.removeUnusedImports ?? optionsConfig.importSortRemoveUnused ?? false
567
542
  };
568
543
  let processedImports = imports;
569
- if (config.removeUnusedImports) {
544
+ if (finalConfig.removeUnusedImports) {
570
545
  const lastImport = imports[imports.length - 1];
571
546
  const codeAfterImports = text.slice(lastImport.end ?? 0);
572
547
  processedImports = removeUnusedImportsFromStatements(imports, codeAfterImports);
573
548
  }
574
- const sortedImports = sortImports(processedImports, config);
549
+ const sortedImports = sortImports(processedImports, finalConfig);
575
550
  const mergedImports = mergeImports(sortedImports);
576
551
  let formattedImports;
577
- if (config.getGroup) {
578
- const groups = groupImports(mergedImports, config);
579
- const sortedGroups = sortGroups(groups, config);
580
- formattedImports = formatGroups(sortedGroups, config);
552
+ if (finalConfig.getGroup) {
553
+ const groups = groupImports(mergedImports, finalConfig);
554
+ const sortedGroups = sortGroups(groups, finalConfig);
555
+ formattedImports = formatGroups(sortedGroups, finalConfig);
581
556
  } else formattedImports = formatImportStatements(mergedImports);
582
557
  const firstImport = imports[0];
583
558
  const lastImport = imports[imports.length - 1];
@@ -593,55 +568,99 @@ function preprocessImports(text, options) {
593
568
  return text;
594
569
  }
595
570
  }
596
- const babelParser = src_require("prettier/parser-babel").parsers.babel;
597
- const typescriptParser = src_require("prettier/parser-typescript").parsers.typescript;
598
- const babelTsParser = src_require("prettier/parser-babel").parsers["babel-ts"];
599
- function createPluginInstance() {
600
- return {
601
- parsers: {
602
- babel: {
603
- ...babelParser,
604
- preprocess: preprocessImports
605
- },
606
- typescript: {
607
- ...typescriptParser,
608
- preprocess: preprocessImports
609
- },
610
- "babel-ts": {
611
- ...babelTsParser,
612
- preprocess: preprocessImports
613
- }
571
+ const { parsers: { babel } } = src_require("prettier/parser-babel");
572
+ const { parsers: { typescript } } = src_require("prettier/parser-typescript");
573
+ const { parsers: { "babel-ts": babelTs } } = src_require("prettier/parser-babel");
574
+ function createCombinedPreprocess(parserName, config) {
575
+ return function(text, options) {
576
+ const otherPlugins = config.otherPlugins || [];
577
+ if (0 === otherPlugins.length) return preprocessImports(text, options, config);
578
+ const prettierOptions = config.prettierOptions || {};
579
+ const mergedOptions = {
580
+ ...options,
581
+ ...prettierOptions
582
+ };
583
+ const preprocessFunctions = [];
584
+ preprocessFunctions.push((text, options)=>preprocessImports(text, options, config));
585
+ for (const plugin of otherPlugins){
586
+ const parser = plugin?.parsers?.[parserName];
587
+ if (parser?.preprocess && "function" == typeof parser.preprocess) preprocessFunctions.push(parser.preprocess);
588
+ }
589
+ let processedText = text;
590
+ for (const preprocess of preprocessFunctions)try {
591
+ processedText = preprocess(processedText, mergedOptions);
592
+ } catch (error) {
593
+ console.warn("Plugin preprocess failed:", error instanceof Error ? error.message : String(error));
594
+ }
595
+ return processedText;
596
+ };
597
+ }
598
+ function createPluginInstance(config = {}) {
599
+ const baseOptions = {
600
+ importSortSeparator: {
601
+ type: "string",
602
+ category: "Import Sort",
603
+ description: "分组之间的分隔符"
614
604
  },
615
- options: {
616
- sortImportsConfigPath: {
617
- type: "string",
618
- category: "Import Sort",
619
- description: "配置文件路径,用于加载自定义排序配置"
620
- },
621
- importSortSeparator: {
622
- type: "string",
623
- category: "Import Sort",
624
- description: "分组之间的分隔符"
625
- },
626
- importSortSideEffect: {
627
- type: "boolean",
628
- category: "Import Sort",
629
- description: "是否对副作用导入进行排序",
630
- default: false
631
- },
632
- importSortRemoveUnused: {
633
- type: "boolean",
634
- category: "Import Sort",
635
- description: "是否删除未使用的导入",
636
- default: false
605
+ importSortSideEffect: {
606
+ type: "boolean",
607
+ category: "Import Sort",
608
+ description: "是否对副作用导入进行排序",
609
+ default: false
610
+ },
611
+ importSortRemoveUnused: {
612
+ type: "boolean",
613
+ category: "Import Sort",
614
+ description: "是否删除未使用的导入",
615
+ default: false
616
+ }
617
+ };
618
+ const otherPlugins = config.otherPlugins || [];
619
+ const mergedOptions = {
620
+ ...baseOptions
621
+ };
622
+ for (const plugin of otherPlugins)if (plugin?.options) Object.assign(mergedOptions, plugin.options);
623
+ const mergedPrinters = {};
624
+ for (const plugin of otherPlugins)if (plugin?.printers) Object.assign(mergedPrinters, plugin.printers);
625
+ const mergedParsers = {};
626
+ const parserNames = [
627
+ "babel",
628
+ "typescript",
629
+ "babel-ts"
630
+ ];
631
+ const baseParsers = {
632
+ babel,
633
+ typescript,
634
+ "babel-ts": babelTs
635
+ };
636
+ for (const parserName of parserNames){
637
+ const baseParser = baseParsers[parserName];
638
+ let merged = {
639
+ ...baseParser
640
+ };
641
+ for (const plugin of otherPlugins){
642
+ const otherParser = plugin?.parsers?.[parserName];
643
+ if (otherParser) {
644
+ const { preprocess, ...otherAttrs } = otherParser;
645
+ merged = {
646
+ ...merged,
647
+ ...otherAttrs
648
+ };
637
649
  }
638
650
  }
651
+ merged.preprocess = createCombinedPreprocess(parserName, config);
652
+ mergedParsers[parserName] = merged;
653
+ }
654
+ const result = {
655
+ parsers: mergedParsers,
656
+ options: mergedOptions
639
657
  };
658
+ if (Object.keys(mergedPrinters).length > 0) result.printers = mergedPrinters;
659
+ return result;
640
660
  }
641
- const src_plugin = createPluginInstance();
642
661
  function createPlugin(config = {}) {
643
- src_userConfig = config;
644
- return createPluginInstance();
662
+ return createPluginInstance(config);
645
663
  }
664
+ const src_plugin = createPluginInstance();
646
665
  const src = src_plugin;
647
666
  export { createPlugin, src as default };
package/dist/parser.d.ts CHANGED
@@ -1,2 +1,3 @@
1
- import { ImportStatement } from "./types"; /** 解析导入语句 */
1
+ import { ImportStatement } from "./types";
2
+ /** 解析导入语句 */
2
3
  export declare function parseImports(code: string): ImportStatement[];
package/dist/sorter.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { Group, ImportContent, ImportStatement, PluginConfig } from "./types"; /** 导入类型 */
1
+ import { Group, ImportContent, ImportStatement, PluginConfig } from "./types";
2
2
  /** 合并后的配置 */
3
- export interface MergedConfig extends Omit<Required<PluginConfig>, "separator" | "removeUnusedImports"> {
3
+ export interface MergedConfig extends Omit<Required<PluginConfig>, "separator" | "removeUnusedImports" | "otherPlugins" | "prettierOptions"> {
4
4
  separator: PluginConfig["separator"];
5
5
  removeUnusedImports: boolean;
6
6
  }
package/dist/types.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { Plugin } from "prettier";
1
2
  /** 导入内容 */
2
3
  export interface ImportContent {
3
4
  /** 导入的内容的名称 */
@@ -67,4 +68,8 @@ export interface PluginConfig {
67
68
  sortSideEffect?: boolean;
68
69
  /** 是否删除未使用的导入,默认为 false */
69
70
  removeUnusedImports?: boolean;
71
+ /** 要合并的其他 Prettier 插件,按传入顺序执行 */
72
+ otherPlugins?: Plugin[];
73
+ /** 传递给其他插件的 Prettier 配置选项 */
74
+ prettierOptions?: Record<string, any>;
70
75
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@1adybug/prettier-plugin-sort-imports",
3
3
  "type": "module",
4
- "version": "0.0.5",
4
+ "version": "0.0.7",
5
5
  "description": "一个 Prettier 插件,用于对 JavaScript/TypeScript 文件的导入语句进行分组和排序",
6
6
  "keywords": [
7
7
  "prettier",
@@ -54,6 +54,7 @@
54
54
  "@types/bun": "latest",
55
55
  "@types/node": "^22.18.6",
56
56
  "prettier": "^3.6.2",
57
+ "prettier-plugin-tailwindcss": "^0.7.0",
57
58
  "supports-color": "^10.2.2",
58
59
  "typescript": "^5.9.2"
59
60
  },