Skip to content

Sortwind is an opinionated Tailwind CSS class sorter for Visual Studio Code. It enforces consistent ordering of classes by parsing your code and reprinting class tags to follow a given order.

License

Notifications You must be signed in to change notification settings

guidomodarelli/sortwind

Repository files navigation

Banner

status CircleCI License FOSSA Status https://good-labs.github.io/greater-good-affirmation/assets/images/badge.svg support

Sortwind is an opinionated Tailwind CSS class sorter for Visual Studio Code. It enforces consistent ordering of classes by parsing your code and reprinting class tags to follow a given order.

Explainer

Note

Sortwind runs on save, will remove duplicate classes and can even sort entire workspaces.

Table of contents

1. Usage

You can install Sortwind via the VS Code Marketplace, or package it yourself using vsce. Sortwind works globally once installed and will run on save if a tailwind.config.js file is present within your working directory.

You can also trigger Sortwind by:

  • Pressing ALT + Shift + T on Mac
  • Pressing CTRL + ALT + T on Windows
  • Pressing CTRL + ALT + T on Linux

Sortwind can sort individual files by running 'Sort Tailwind CSS Classes' via the Command Palette. Workspaces can also be sorted by running 'Sort Tailwind CSS Classes on Entire Workspace'.

Any breakpoints or unknown classes will be moved to the end of the class list, whilst duplicate classes will be removed.

2. Customization

Sortwind ships with a default class order (located in package.json). You can edit this (and other settings) to your liking on the extension settings page.

2.1. sortwind.classRegex

An object with language IDs as keys and their values determining the regex to search for Tailwind CSS classes. The default is located in package.json but this can be customized to suit your needs.

There can be multiple capturing groups, that should only contain a string with Tailwind CSS classes (without any apostrophes etc.). If a new group, which doesn't contain the class string, is created, ensure that it is non-capturing by using (?:).

Example from package.json:

"sortwind.classRegex": {
    "html": "\\bclass\\s*=\\s*[\\\"\\']([_a-zA-Z0-9\\s\\-\\:\\/]+)[\\\"\\']",
    "javascriptreact": "(?:\\bclassName\\s*=\\s*[\\\"\\']([_a-zA-Z0-9\\s\\-\\:\\/]+)[\\\"\\'])|(?:\\btw\\s*`([_a-zA-Z0-9\\s\\-\\:\\/]*)`)"
}

2.1.1. Multi-step Regex

A multi-step regex can be specified by using an array of regexes that are executed sequentially.

Example from package.json:

"sortwind.classRegex": {
    "javascript": [
        "(?:\\bclass(?:Name)?\\s*=\\s*(?:{([\\w\\d\\s_\\-:/${}()[\\]\"'`,]+)})|([\"'`][\\w\\d\\s_\\-:/]+[\"'`]))|(?:\\btw\\s*(`[\\w\\d\\s_\\-:/]+`))",
        "(?:[\"'`]([\\w\\d\\s_\\-:/${}()[\\]\"']+)[\"'`])"
    ],
}

The first regex will look for JSX class or className attributes or twin.macro usage.

The second regex will then look for class names to be sorted within these matches.

2.1.2. Configuration Object

Optionally a configuration object can be passed to specify additional options for sorting class names.

  • regex - specifies the regex to be used to find class names
  • separator - regex pattern that is used to separate class names (default: "\\s+")
  • replacement - string used to replace separator matches (default: " ")

Example from package.json:

"sortwind.classRegex": {
    "jade": [
        {
            "regex": "\\.([\\._a-zA-Z0-9\\-]+)",
            "separator": "\\.",
            "replacement": "."
        },
        "\\bclass\\s*=\\s*[\\\"\\']([_a-zA-Z0-9\\s\\-\\:\\/]+)[\\\"\\']"
    ],
}

2.1.3. Debugging Custom Regex

To debug custom classRegex, you can use the code below:

// Your test string here
const editorText = `
  export const Layout = ({ children }) => (
    <div class="h-screen">
      <div className="w-64 h-full bg-blue-400 relative"></div>
      <div>{children}</div>
    </div>
  )
`
// Your Regex here
const regex = /(?:\b(?:class|className)?\s*=\s*{?[\"\']([_a-zA-Z0-9\s\-\:/]+)[\"\']}?)/
const classWrapperRegex = new RegExp(regex, 'gi')

let classWrapper
while ((classWrapper = classWrapperRegex.exec(editorText)) !== null) {
  const wrapperMatch = classWrapper[0]
  const valueMatchIndex = classWrapper.findIndex((match, idx) => idx !== 0 && match)
  const valueMatch = classWrapper[valueMatchIndex]

  console.log('classWrapper', classWrapper)
  console.log('wrapperMatch', wrapperMatch)
  console.log('valueMatchIndex', valueMatchIndex)
  console.log('valueMatch', valueMatch)
}

The result of valueMatch should be the class text exactly, with no other characters.

Good example value: valueMatch w-64 h-full bg-blue-400 relative

Note: Changes made to Sortwind's JSON configuration options may not take effect immediately. When experimenting with custom classRegex, after each change you should open the control palette (Ctrl/Cmd + Shift + P) and run Developer: Reload Window to ensure changes are applied.


2.2. sortwind.defaultSortOrder

An array that determines Sortwind's default sort order.

2.3. sortwind.removeDuplicates

Sortwind will remove duplicate class names by default. This can be toggled on or off.

"sortwind.removeDuplicates": true

2.4. sortwind.prependCustomClasses

Sortwind will append custom class names by default. They can be prepended instead.

"sortwind.prependCustomClasses": true

2.5. sortwind.runOnSave

Sortwind will run on save by default (if a tailwind.config.js file is present within your working directory). This can be toggled on or off.

"sortwind.runOnSave": true

3. Contributing

Sortwind is open-source and contributions are always welcome. If you're interested in submitting a pull request, please take a moment to review CONTRIBUTING.md.

4. Analytics

Alt

5. License

FOSSA Status

Important

This project is a fork of Headwind, created by Ryan Heybourn.

About

Sortwind is an opinionated Tailwind CSS class sorter for Visual Studio Code. It enforces consistent ordering of classes by parsing your code and reprinting class tags to follow a given order.

Resources

License

Stars

Watchers

Forks

Sponsor this project

Packages

No packages published