biome-tailwind-sorter
v0.2.8
Published
A high-performance Rust CLI tool for sorting Tailwind CSS classes according to official order
Maintainers
Readme
biome-tailwind-sorter
A high-performance Rust-based formatter for automatically sorting Tailwind CSS classes according to the official recommended order, with advanced cursor position preservation for seamless editor integration.
🚀 Features
- ✅ High Performance - Written in Rust for blazing fast formatting
- ✅ Cursor Position Preservation - Maintains cursor position during formatting (solves VS Code cursor jumping!)
- ✅ Automatic Formatting - Sorts Tailwind classes on file save
- ✅ CLI Tool - Standalone formatter for any project
- ✅ Multi-language Support - HTML, JSX, TSX, and Vue files
- ✅ Multi-line Classes - Preserves formatting for multi-line class definitions
- ✅ Smart Detection - Only processes files that contain Tailwind classes
- ✅ Editor Integration - Perfect for VS Code with Run on Save extension
📦 Installation
npm install --save-dev biome-tailwind-sorter🔧 Usage
Method 1: CLI Tool (Recommended)
# Format specific files
npx biome-tailwind-sorter --write src/components/Button.tsx
# Format all supported files in a directory
npx biome-tailwind-sorter --write src/
# Check if files need formatting (useful in CI)
npx biome-tailwind-sorter --check src/
# With cursor position preservation (for editor integration)
npx biome-tailwind-sorter --write --preserve-cursor --cursor-offset 245 src/component.tsxMethod 2: VS Code Integration with Run on Save
For seamless VS Code integration:
Install the Run on Save extension
Add to your VS Code
settings.json:
{
"emeraldwalk.runonsave": {
"commands": [
{
"match": "\\.(jsx?|tsx?|html|vue|astro)$",
"cmd": "npx biome-tailwind-sorter --write --preserve-cursor --cursor-offset ${cursor} ${file}"
}
]
}
}Method 3: Direct Cargo Usage (Advanced)
If you have Rust installed, you can use Cargo directly for maximum performance:
# Build the project
cargo build --release
# Run the formatter
cargo run --release -- --write src/🎯 Cursor Position Solution ✅ SOLVED
This project completely solves the cursor jumping problem that occurs with formatters in VS Code:
The Problem (Now Solved!)
When using external formatters, VS Code typically loses track of cursor position because the file content changes during formatting, causing the cursor to jump to unexpected locations.
Our Solution
The CLI tool provides cursor preservation through:
CLI with Cursor Preservation
For other editors or advanced use cases:
- Input Tracking: Accepts cursor position via
--cursor-offsetflag - Smart Mapping: Calculates where your cursor should be in the formatted content
- Position Output: Returns new cursor position via stderr:
CURSOR_POSITION:line:column:offset - Editor Integration: Compatible with any editor that can parse the output
Integration Examples
Run on Save Integration:
npx biome-tailwind-sorter --write --preserve-cursor --cursor-offset ${cursor} ${file}${cursor}- Current cursor offset from editor${file}- File path from editor- Tool outputs new position for editor to restore
📝 Examples
Before (unsorted):
<div
className="
text-white
bg-red-500
p-4
hover:bg-red-600
rounded-lg
font-semibold
"
>
Button
</div>After (sorted):
<div
className="
p-4
font-semibold
text-white
bg-red-500
rounded-lg
hover:bg-red-600
"
>
Button
</div>Single line example:
Before: <div className="text-white bg-red-500 p-4" />
After: <div className="p-4 bg-red-500 text-white" />
📁 Supported File Types
- HTML -
classattributes - JSX/TSX -
classNameattributes - Vue -
classattributes - Astro -
classandclassNameattributes
🎨 Class Ordering
The plugin follows Tailwind's official class ordering:
- Layout -
container,box-border,block,inline-block,flex,grid, etc. - Position -
static,fixed,absolute,relative,sticky - Top/Right/Bottom/Left -
inset-*,top-*,right-*, etc. - Visibility -
visible,invisible,collapse - Z-Index -
z-* - Flex & Grid -
flex-row,justify-center,items-center, etc. - Spacing -
p-*,m-*,space-*, etc. - Sizing -
w-*,h-*,min-w-*,max-w-*, etc. - Typography -
font-*,text-*,tracking-*, etc. - Backgrounds -
bg-*,from-*,via-*,to-* - Borders -
border-*,rounded-*,ring-* - Effects -
shadow-*,opacity-* - Filters -
filter,blur-*,brightness-*, etc. - Transitions -
transition-*,duration-*,ease-* - Transforms -
transform,scale-*,rotate-*, etc. - Interactivity -
cursor-*,pointer-events-*, etc.
Responsive modifiers (sm:, md:, lg:, etc.) and state modifiers (hover:, focus:, etc.) are preserved and sorted appropriately.
⚙️ CLI Options
biome-tailwind-sorter [options] <files...>
Options:
-w, --write Write sorted classes back to files
-c, --check Check if files need sorting (exit code 1 if changes needed)
-v, --verbose Verbose output
--preserve-cursor Preserve cursor position (for editor integration)
--cursor-line <LINE> Current cursor line (0-based)
--cursor-column <COLUMN> Current cursor column (0-based)
--cursor-offset <OFFSET> Current cursor offset
-h, --help Print help
-V, --version Print version🔧 Advanced Usage
Programmatic API
You can use the Rust library programmatically in other Rust projects:
use biome_tailwind_sorter::{sort_tailwind_classes, format_file_content};
// Sort classes
let classes = vec!["text-white".to_string(), "bg-red-500".to_string(), "p-4".to_string()];
let sorted = sort_tailwind_classes(&classes);
println!("{:?}", sorted); // ["p-4", "bg-red-500", "text-white"]
// Format file content
let html = r#"<div class="text-red-500 p-4 flex">content</div>"#;
let (formatted, _) = format_file_content(html, None);
println!("{}", formatted);Custom Tailwind Config Support
The plugin automatically detects standard Tailwind classes. For custom utilities defined in your tailwind.config.js, the plugin will leave them in their original position to avoid breaking functionality.
🚀 Performance Benefits
Rust vs TypeScript/Node.js:
- ⚡ 10-50x faster execution time
- 🧠 Lower memory usage
- 🔧 Zero runtime dependencies
- ⚙️ Optimized binary with release builds
- 🔄 Better concurrent processing
Real-world impact:
- Large codebases format in milliseconds instead of seconds
- No noticeable delay during save operations
- Comprehensive test coverage with 19 passing tests
Note: The tool is currently optimized for HTML class attributes and may have parsing limitations with complex JSX/TSX syntax. For production use with React components, thorough testing is recommended.
🆚 Comparison with Prettier Plugin
This plugin is designed to work independently and offers several advantages:
- ✅ Cursor Position Preservation - Unique feature not available elsewhere
- ✅ Rust Performance - Significantly faster than Node.js alternatives
- ✅ No Dependencies - Single binary, no Node.js runtime required
- ✅ Editor Integration - Purpose-built for seamless IDE experience
- ✅ Standalone CLI - Works in any project setup
- ✅ Memory Efficient - Lower resource usage
🔨 Development
Building the project:
cargo build --releaseRunning tests:
cargo testDevelopment mode:
cargo buildNPM scripts:
npm run build # Builds Rust release binary
npm run dev # Builds Rust debug binary
npm run test # Runs Rust tests🧪 Testing
The project includes comprehensive tests for:
- Class parsing and extraction
- Tailwind class detection
- Sorting algorithm correctness
- Cursor position preservation
- File processing and CLI functionality
Run tests with:
cargo test🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Make your changes in Rust (not TypeScript)
- Add tests for new functionality
- Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
☕ Support
If this project helps you, consider supporting its development:
📄 License
MIT License - see the LICENSE file for details.
🙏 Acknowledgments
- Tailwind CSS for the official class ordering specification
- Biome for inspiration on fast tooling
- Rust Community for the excellent ecosystem
- Run on Save Extension for VS Code integration capabilities
