@caipira/prettier-plugin-sort-imports
v0.0.1
Published
A prettier plugin for sorting imports in a configurable way.
Downloads
102
Maintainers
Readme
@caipira/prettier-plugin-sort-imports
Forked from prettier-plugin-sort-imports.
A Prettier v3+ plugin for sorting imports in a configurable way:
- Import length or line length sorting
- Alphabetical sorting
- Splitting imports into separate statements by kind
Example:

Installation
# npm
npm install --save-dev @caipira/prettier-plugin-sort-imports
# pnpm
pnpm add -D @caipira/prettier-plugin-sort-imports
# yarn
yarn add -D @caipira/prettier-plugin-sort-importsQuick Start
Add the plugin to your Prettier config:
// prettier.config.js
module.exports = {
sortingMethod: 'importLength',
plugins: ['@caipira/prettier-plugin-sort-imports'],
};Option Reference
All options are Prettier options, so place them in your Prettier config.
| Option | Type | Default | Description |
| ------------------------ | -------------------------------------------------- | -------------------- | ---------------------------------------------------------------------------------------------------------------- |
| sortingMethod | 'lineLength' \| 'importLength' \| 'alphabetical' | 'lineLength' | Primary sort metric inside each import group. |
| sortingOrder | 'ascending' \| 'descending' | 'descending' | Reverses sorted output produced by the selected method. |
| stripNewlines | boolean | false | Merges adjacent import blocks when only whitespace/comments separate them. |
| importTypeOrder | IMPORT_TYPE[] | ['all'] | Defines group buckets and their group order. |
| packageJSONFiles | string[] | ['./package.json'] | Package manifests used to detect npm/dependency imports. |
| newlineBetweenTypes | boolean | false | Inserts a blank line between non-empty import type groups. |
| splitByImportTypeOrder | boolean | false | Forces grouping by importTypeOrder, extracts inline type specifiers, and splits groups into separate blocks. |
Import Type Values
importTypeOrder accepts these values:
all: single bucket for all imports (disables type grouping)NPMPackages: npm/dependency imports (plus Node built-ins andbun)NPMPackagesType: type-only npm importsimportsType: all type-only imports (npm + local)localImportsValue: local non-type importslocalImportsType: local type-only importslocalImports: all local imports (type + value)components: imports ending in.vueor.tsx
How Sorting Works
The plugin runs in this order:
- Skip file if ignore directive is present.
- If enabled, split mixed imports into value import +
import typeimport. - Sort specifiers inside multi-line named imports.
- Detect import blocks.
- Group imports by
importTypeOrder. - Sort each group by
sortingMethod/sortingOrder. - Rebuild blocks and optional inter-group blank lines.
1) sortingMethod
lineLength
Sorts by full import statement text length (import ... from 'x').
importLength
Sorts by import clause length (specifier area), not full line length.
Examples:
import { a, bb } from 'x'compares by{ a, bb }import Default from 'x'compares byDefaultimport type { Foo } from 'x'compares by{ Foo }import 'x'has specifier length0
alphabetical
Sorts by moduleSpecifier string ('react', './file', etc.).
2) sortingOrder
sortingOrder reverses the result produced by the method sorter.
- For length-based methods,
descendingmeans longer first,ascendingmeans shorter first. - For alphabetical, current behavior is legacy:
descendingresults in A to Z, andascendingresults in Z to A.
3) stripNewlines
When false, import blocks are split on blank lines.
When true, blocks separated only by whitespace/comments are merged and sorted together.
Code between imports still keeps blocks separate.
4) importTypeOrder
Defines grouping buckets and group order. Within each group, normal sorting still applies.
Classification precedence
When multiple categories could match, classification priority is:
componentsimportsTypeNPMPackagesTypelocalImportsTypeNPMPackageslocalImportsValuelocalImports
5) packageJSONFiles
Used to detect npm package imports for npm-related buckets.
- reads both
dependenciesanddevDependencies - supports multiple package files
- absolute paths are respected
- relative paths are resolved from the nearest Prettier config location (fallback: process cwd)
- Node built-ins are treated as npm bucket imports
bunis always treated as a built-in bucket import
6) newlineBetweenTypes
If true, inserts one blank line between non-empty import groups.
7) splitByImportTypeOrder
When enabled:
- import blocks are effectively merged for grouping (acts like strip-then-regroup)
- group boundaries follow
importTypeOrder - blank lines are inserted between resulting groups
- mixed imports are split:
import { Kind, type FieldNode } from './types';becomes:
import { Kind } from './types';
import type { FieldNode } from './types';- generated multi-line imports are also passed through specifier sorting
Multi-Line Specifier Sorting
All multi-line named imports are sorted internally.
- single-line named imports are not rewritten
- with
alphabetical, specifiers sort lexicographically - with
lineLengthorimportLength, specifiers sort by specifier text length (with alphabetical tie-break) typeprefix is ignored for comparison keys (type Foocompares asFoo)
Interaction Rules and Validation
The plugin validates combinations and throws for invalid setups.
Rules
['all']must be alone.localImportscannot be combined withlocalImportsValueorlocalImportsType.- If you use legacy local split (
localImportsValue/localImportsType) withoutimportsTypeorNPMPackagesType, both value and type options must be present together. importsTypecannot be combined withlocalImportsTypeorNPMPackagesType.- If you use one of
localImports,localImportsValue, orlocalImportsType, you must also include at least one npm bucket (NPMPackagesorNPMPackagesType).
Valid examples
{
"importTypeOrder": ["all"]
}{
"importTypeOrder": ["NPMPackages", "localImports"]
}{
"importTypeOrder": [
"NPMPackagesType",
"localImportsType",
"NPMPackages",
"localImportsValue"
]
}{
"importTypeOrder": [
"importsType",
"NPMPackages",
"localImports",
"components"
]
}Invalid examples
{
"importTypeOrder": ["all", "NPMPackages"]
}{
"importTypeOrder": ["importsType", "localImportsType", "NPMPackages"]
}{
"importTypeOrder": ["localImportsType", "NPMPackages"]
}Recommended Configurations
A) Minimal, stable behavior
{
"sortingMethod": "lineLength",
"sortingOrder": "descending",
"importTypeOrder": ["all"]
}B) NPM first, local second
{
"sortingMethod": "alphabetical",
"sortingOrder": "descending",
"importTypeOrder": ["NPMPackages", "localImports"],
"newlineBetweenTypes": true
}C) Strict type/value grouping with splitting
{
"sortingMethod": "importLength",
"sortingOrder": "ascending",
"importTypeOrder": [
"importsType",
"NPMPackages",
"localImportsValue",
"components"
],
"splitByImportTypeOrder": true,
"newlineBetweenTypes": true
}D) Monorepo package detection
{
"importTypeOrder": ["NPMPackages", "localImports"],
"packageJSONFiles": [
"./package.json",
"./packages/app/package.json",
"./packages/ui/package.json"
]
}Ignore Controls
Skip an entire file:
// sort-imports-ignoreSkip a range:
// sort-imports-begin-ignore
// ...imports or code here...
// sort-imports-end-ignoreNotes:
- begin/end ignore markers must be balanced
- unmatched markers skip sorting for the file and print a warning
Compatibility issues with other plugins
When combined with other plugins that make use of private Prettier APIs (for example prettier-plugin-tailwindcss), you will need combine them into a single plugin:
// prettier.config.js:
const pluginTailwindcss = require('prettier-plugin-tailwindcss');
const pluginSortImports = require('@caipira/prettier-plugin-sort-imports');
async function parseWithTailwindTypescript(...args) {
const tsParser = pluginTailwindcss.parsers.typescript;
if (tsParser && typeof tsParser.parse === 'function') {
return tsParser.parse(...args);
}
if (typeof tsParser === 'function') {
try {
const maybeParser = await tsParser();
if (maybeParser && typeof maybeParser.parse === 'function') {
return maybeParser.parse(...args);
}
} catch (_err) {}
return tsParser(...args);
}
}
/** @type {import("prettier").Plugin} */
const plugin = {
options: pluginSortImports.options,
parsers: {
typescript: {
...pluginSortImports.parsers.typescript,
parse: parseWithTailwindTypescript,
},
},
};
module.exports = {
plugins: [plugin],
// Your prettier options
arrowParens: 'always',
bracketSpacing: true,
printWidth: 90,
semi: true,
tabWidth: 4,
singleQuote: true,
useTabs: false,
trailingComma: 'es5',
vueIndentScriptAndStyle: false,
singleAttributePerLine: true,
// Options for @caipira/prettier-plugin-sort-imports
sortingMethod: 'importLength',
sortingOrder: 'ascending',
importTypeOrder: [
'importsType',
'NPMPackages',
'localImportsValue',
'components',
],
splitByImportTypeOrder: true,
newlineBetweenTypes: true,
};