eslint-plugin-pretty-import 0.1.1
Install from the command line:
Learn more about npm packages
$ npm install @kamiya4047/eslint-plugin-pretty-import@0.1.1
Install via package.json:
"@kamiya4047/eslint-plugin-pretty-import": "0.1.1"
About this version
The import sorting plugin that does it my way. After years of being mildly annoyed by other sorting plugins, I finally wrote one that makes imports look exactly how I want them.
- Opinionated 6-Group Hierarchy - My preferred way of organizing imports
-
CSS Groups - Moves CSS to bottom (
⚠️ might break your styles!) - River-Based Side Effects - Preserves JS execution order (the only non-negotiable part)
- Count-Based Sorting - Busier imports get priority (weird, but I like it)
- Character Priority - Creates visual hierarchy I find pleasing
- Full ESLint v9 Support - Built for flat config format
I've tried a lot of import sorting plugins and none of them fit my preference.
So I built my own. This plugin is unapologetically opinionated – it sorts imports exactly the way I think they should look after years of staring at code. It's not based on any standard or committee decision. It's based on what makes my brain happy when I open a file.
[!WARNING] This plugin might break your project. It moves CSS imports to the bottom which could affect load order. It uses non-standard sorting that your team might hate. It's definitely not for everyone. Actually, it's probably just for me and the three other people who think like me.
You might hate it. That's cool! But if you've also been searching for that just right import order, maybe we share the same aesthetic.
npm install --save-dev @kamiya4047/eslint-plugin-pretty-import
# or
yarn add --dev @kamiya4047/eslint-plugin-pretty-import
# or
bun add --dev @kamiya4047/eslint-plugin-pretty-importFrom GitHub Packages:
npm install --save-dev @kamiya4047/eslint-plugin-pretty-import --registry=https://npm.pkg.github.com// eslint.config.js
import prettyImport from '@kamiya4047/eslint-plugin-pretty-import';
export default [
{
plugins: { 'pretty-import': prettyImport },
rules: {
'pretty-import/separate-type-imports': 'error',
'pretty-import/sort-import-groups': ['error', {
localPatterns: ['@/', '~/'],
groupStyleImports: true,
}],
'pretty-import/sort-import-names': 'error',
}
}
];...or use Shared configurations:
// eslint.config.js
import prettyImport from '@kamiya4047/eslint-plugin-pretty-import';
export default [
// Warn (warn severity for sorting rules)
prettyImport.configs.warn,
// Or error (error severity with advanced options)
prettyImport.configs.error,
];| Rule | Description | Fixable |
|---|---|---|
sort-import-groups |
Groups and sorts imports with CSS grouping | ✅ |
sort-import-names |
Sorts named imports within import statements | ✅ |
separate-type-imports |
Enforces separate import type declarations |
✅ |
The main rule for organizing imports into groups and sorts them.
- Groups are
- Groups are separated by exactly one blank line
- No blank lines within groups
{
// Path aliases like ['@/', '~/']
localPatterns: string[];
// Group CSS at bottom (default: true)
groupStyleImports: boolean;
// Built-in prefixes (default: ['node:', 'bun:'])
builtinModulePrefixes: string[];
}Sorts the named imports within each import statement.
{
// Case insensitive sorting (default: false)
caseInsensitive: boolean;
}Before:
import { useState, useEffect, useMemo } from 'react';After:
import { useEffect, useMemo, useState } from 'react';Enforces separation of type imports from value imports. This rule runs first to prepare imports for the sorting rules.
Before:
import { useState, type ComponentProps, type FC } from 'react';
import { type User, createUser } from './user';After:
import { useState } from 'react';
import type { ComponentProps, FC } from 'react';
import { createUser } from './user';
import type { User } from './user';This rule is designed to work seamlessly with the sorting rules:
-
separate-type-imports runs first and converts inline
typeimports - sort-import-groups then organizes everything into proper groups
- sort-import-names finally sorts named imports alphabetically
All three rules can be used together without conflicts.
Imports with more specifiers come first within their group:
// More imports (3) come before fewer imports (1)
import { useEffect, useMemo, useState } from 'react';
import { BehaviorSubject, Observable } from 'rxjs';
import { z } from 'zod';// Original
import { utils } from '@/utils';
import './reset.css';
import 'polyfill';
import './theme.css';
import { Component } from './component';
// After sorting
import { utils } from '@/utils';
import 'polyfill'; // JavaScript river stays
import { Component } from './component';
import './reset.css'; // CSS moved to bottom
import './theme.css';// Special characters → UPPERCASE → lowercase
import { $store, AUTH_TOKEN, apiClient } from './constants';export default [
{
plugins: { 'pretty-import': prettyImport },
rules: {
'pretty-import/separate-type-imports': 'error',
'pretty-import/sort-import-groups': ['error', {
localPatterns: ['@/', '~/'],
groupStyleImports: true
}],
'pretty-import/sort-import-names': 'error'
}
}
];export default [
{
plugins: { 'pretty-import': prettyImport },
rules: {
'pretty-import/separate-type-imports': 'error',
'pretty-import/sort-import-groups': ['error', {
localPatterns: ['@app/', '@packages/', '@shared/'],
builtinModulePrefixes: ['node:', 'bun:', 'deno:'],
groupStyleImports: true
}],
'pretty-import/sort-import-names': 'error'
}
}
];export default [
// Warn: warn severity for sorting rules
prettyImport.configs.warn,
// Error: error severity with additional options
prettyImport.configs.error,
];Look, I've stared at a lot of import statements. After years of squinting at the top of files, certain patterns just started to feel right:
- Built-ins first - I want to know what runtime stuff you're using before anything else
-
Named import counts - More imports first creates a visual triangle shape
when sorted by count:
{a, b, c, d, e}before{z} - CSS at the bottom - Styles are makeup, logic is bone structure. Bone structure first
- Rivers preserve flow - Side effects stay where you put them because breaking things is bad
Is this objectively correct? No. Is this how imports look best to me? Absolutely.
- Group CSS - Move all CSS imports to the bottom
- Split by rivers - JavaScript side effects create section boundaries
- Sort sections - Apply 6-group hierarchy to each section
- Reconstruct - Reassemble with rivers preserved and CSS at bottom
CSS at the top of a file is like wearing your shirt before your underwear. Sure, it works, but it feels wrong:
- JavaScript = the actual logic that runs
- CSS = the pretty colors
- Logic before beauty, always
Note: This could totally break your styles if you depend on CSS load order. But my projects don't, so... 🤷
When sorted by import count, it creates a satisfying visual triangle shape:
import { useCallback, useContext, useEffect, useMemo, useState } from 'react';
import { combineLatest, fromEvent, map, startWith } from 'rxjs';
import { clsx, twMerge } from 'tailwind-merge';
import { z } from 'zod';This triangle pattern just feels right – more important imports get visual priority.
- ESLint: v8.0.0 or higher (v9 recommended)
- Node.js: v18.0.0 or higher
- TypeScript: Full support with proper type imports handling
# Install dependencies
bun install
# Run tests
bun test
# Build
bun run build
# Lint
bun run lintContributions are welcome! Please read our Contributing Guide for details.
License can be found at [LICENSE].
If you find this plugin useful, consider supporting its development: