npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@caipira/prettier-plugin-sort-imports

v0.0.1

Published

A prettier plugin for sorting imports in a configurable way.

Downloads

102

Readme

@caipira/prettier-plugin-sort-imports

NPM Downloads

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-imports

Quick 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 and bun)
  • NPMPackagesType: type-only npm imports
  • importsType: all type-only imports (npm + local)
  • localImportsValue: local non-type imports
  • localImportsType: local type-only imports
  • localImports: all local imports (type + value)
  • components: imports ending in .vue or .tsx

How Sorting Works

The plugin runs in this order:

  1. Skip file if ignore directive is present.
  2. If enabled, split mixed imports into value import + import type import.
  3. Sort specifiers inside multi-line named imports.
  4. Detect import blocks.
  5. Group imports by importTypeOrder.
  6. Sort each group by sortingMethod/sortingOrder.
  7. 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 by Default
  • import type { Foo } from 'x' compares by { Foo }
  • import 'x' has specifier length 0

alphabetical

Sorts by moduleSpecifier string ('react', './file', etc.).

2) sortingOrder

sortingOrder reverses the result produced by the method sorter.

  • For length-based methods, descending means longer first, ascending means shorter first.
  • For alphabetical, current behavior is legacy: descending results in A to Z, and ascending results 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:

  1. components
  2. importsType
  3. NPMPackagesType
  4. localImportsType
  5. NPMPackages
  6. localImportsValue
  7. localImports

5) packageJSONFiles

Used to detect npm package imports for npm-related buckets.

  • reads both dependencies and devDependencies
  • 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
  • bun is 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 lineLength or importLength, specifiers sort by specifier text length (with alphabetical tie-break)
  • type prefix is ignored for comparison keys (type Foo compares as Foo)

Interaction Rules and Validation

The plugin validates combinations and throws for invalid setups.

Rules

  1. ['all'] must be alone.
  2. localImports cannot be combined with localImportsValue or localImportsType.
  3. If you use legacy local split (localImportsValue/localImportsType) without importsType or NPMPackagesType, both value and type options must be present together.
  4. importsType cannot be combined with localImportsType or NPMPackagesType.
  5. If you use one of localImports, localImportsValue, or localImportsType, you must also include at least one npm bucket (NPMPackages or NPMPackagesType).

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-ignore

Skip a range:

// sort-imports-begin-ignore
// ...imports or code here...
// sort-imports-end-ignore

Notes:

  • 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,
};