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

biome-tailwind-sorter

v0.2.8

Published

A high-performance Rust CLI tool for sorting Tailwind CSS classes according to official order

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.tsx

Method 2: VS Code Integration with Run on Save

For seamless VS Code integration:

  1. Install the Run on Save extension

  2. 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:

  1. Input Tracking: Accepts cursor position via --cursor-offset flag
  2. Smart Mapping: Calculates where your cursor should be in the formatted content
  3. Position Output: Returns new cursor position via stderr: CURSOR_POSITION:line:column:offset
  4. 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 - class attributes
  • JSX/TSX - className attributes
  • Vue - class attributes
  • Astro - class and className attributes

🎨 Class Ordering

The plugin follows Tailwind's official class ordering:

  1. Layout - container, box-border, block, inline-block, flex, grid, etc.
  2. Position - static, fixed, absolute, relative, sticky
  3. Top/Right/Bottom/Left - inset-*, top-*, right-*, etc.
  4. Visibility - visible, invisible, collapse
  5. Z-Index - z-*
  6. Flex & Grid - flex-row, justify-center, items-center, etc.
  7. Spacing - p-*, m-*, space-*, etc.
  8. Sizing - w-*, h-*, min-w-*, max-w-*, etc.
  9. Typography - font-*, text-*, tracking-*, etc.
  10. Backgrounds - bg-*, from-*, via-*, to-*
  11. Borders - border-*, rounded-*, ring-*
  12. Effects - shadow-*, opacity-*
  13. Filters - filter, blur-*, brightness-*, etc.
  14. Transitions - transition-*, duration-*, ease-*
  15. Transforms - transform, scale-*, rotate-*, etc.
  16. 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 --release

Running tests:

cargo test

Development mode:

cargo build

NPM 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.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/AmazingFeature)
  3. Make your changes in Rust (not TypeScript)
  4. Add tests for new functionality
  5. Commit your changes (git commit -m 'Add some AmazingFeature')
  6. Push to the branch (git push origin feature/AmazingFeature)
  7. Open a Pull Request

☕ Support

If this project helps you, consider supporting its development:

Ko-fi

📄 License

MIT License - see the LICENSE file for details.

🙏 Acknowledgments