Skip to content

Commit 6ba6faa

Browse files
thecrypticacenderscorereinink
authored
Allow sorting of custom attributes, functions, and tagged template literals (#155)
* Add opt-in customization features * Update fixtures * wip * wip * wip * wip * wip * Move parsers/printers/options to bottom of the file * Make fixture formatting async * Run fixture tests in parallel * wip * remove concurrency It works when only running the fixtures but not the other tests. Not sure why. * wip * Tweak prettier config * Simplify fixture * Fix CS * Update readme * Merge defaults instead of replacing them * move fixture * Add Vue fixture * Update changelog * Update options docs in readme * Tweak readme * Show sorted classes in readme * Tweak changelog --------- Co-authored-by: _nderscore <[email protected]> Co-authored-by: Jonathan Reinink <[email protected]>
1 parent 78bd35b commit 6ba6faa

File tree

14 files changed

+750
-263
lines changed

14 files changed

+750
-263
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010
### Added
1111

1212
- Added support for `prettier-plugin-marko` ([#151](https://github.com/tailwindlabs/prettier-plugin-tailwindcss/pull/151))
13+
- Allow sorting of custom attributes, functions, and tagged template literals ([#155](https://github.com/tailwindlabs/prettier-plugin-tailwindcss/pull/155))
1314

1415
### Fixed
1516

README.md

Lines changed: 91 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,11 @@ module.exports = {
2121
}
2222
```
2323

24-
## Resolving your Tailwind configuration
24+
## Options
2525

26-
To ensure that the class sorting is taking into consideration any of your project's Tailwind customizations, it needs access to your [Tailwind configuration file](https://tailwindcss.com/docs/configuration) (`tailwind.config.js`).
26+
### Customizing your Tailwind config path
27+
28+
To ensure that the class sorting takes into consideration any of your project's Tailwind customizations, it needs access to your [Tailwind configuration file](https://tailwindcss.com/docs/configuration) (`tailwind.config.js`).
2729

2830
By default the plugin will look for this file in the same directory as your Prettier configuration file. However, if your Tailwind configuration is somewhere else, you can specify this using the `tailwindConfig` option in your Prettier configuration.
2931

@@ -38,6 +40,93 @@ module.exports = {
3840

3941
If a local configuration file cannot be found the plugin will fallback to the default Tailwind configuration.
4042

43+
## Sorting non-standard attributes
44+
45+
By default this plugin only sorts classes in the `class` attribute as well as any framework-specific equivalents like `class`, `className`, `:class`, `[ngClass]`, etc.
46+
47+
You can sort additional attributes using the `tailwindAttributes` option, which takes an array of attribute names:
48+
49+
```js
50+
// prettier.config.js
51+
module.exports = {
52+
tailwindAttributes: ['myClassList'],
53+
}
54+
```
55+
56+
With this configuration, any classes found in the `myClassList` attribute will be sorted:
57+
58+
```jsx
59+
function MyButton({ children }) {
60+
return (
61+
<button myClassList="rounded bg-blue-500 px-4 py-2 text-base text-white">
62+
{children}
63+
</button>
64+
);
65+
}
66+
```
67+
68+
## Sorting classes in function calls
69+
70+
In addition to sorting classes in attributes, you can also sort classes in strings provided to function calls. This is useful when working with libraries like [clsx](https://github.com/lukeed/clsx) or [cva](https://cva.style/).
71+
72+
You can sort classes in function calls using the `tailwindFunctions` option, which takes a list of function names:
73+
74+
```js
75+
// prettier.config.js
76+
module.exports = {
77+
tailwindFunctions: ['clsx'],
78+
}
79+
```
80+
81+
With this configuration, any classes in `clsx()` function calls will be sorted:
82+
83+
```jsx
84+
import clsx from 'clsx'
85+
86+
function MyButton({ isHovering, children }) {
87+
let classes = clsx(
88+
'rounded bg-blue-500 px-4 py-2 text-base text-white',
89+
{
90+
'bg-blue-700 text-gray-100': isHovering,
91+
},
92+
)
93+
94+
return (
95+
<button className={classes}>
96+
{children}
97+
</button>
98+
)
99+
}
100+
```
101+
102+
## Sorting classes in template literals
103+
104+
This plugin also enables sorting of classes in tagged template literals.
105+
106+
You can sort classes in template literals using the `tailwindFunctions` option, which takes a list of function names:
107+
108+
```js
109+
// prettier.config.js
110+
module.exports = {
111+
tailwindFunctions: ['tw'],
112+
}
113+
```
114+
115+
With this configuration, any classes in template literals tagged with `tw` will automatically be sorted:
116+
117+
```jsx
118+
import { View, Text } from 'react-native'
119+
import tw from 'twrnc'
120+
121+
function MyScreen() {
122+
return (
123+
<View style={tw`bg-white p-4 dark:bg-black`}>
124+
<Text style={tw`text-md text-black dark:text-white`}>Hello World</Text>
125+
</View>
126+
)
127+
}
128+
```
129+
41130
## Compatibility with other Prettier plugins
42131

43132
This plugin uses Prettier APIs that can only be used by one plugin at a time, making it incompatible with other Prettier plugins implemented the same way. To solve this we've added explicit per-plugin workarounds that enable compatibility with the following Prettier plugins:

prettier.config.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,7 @@ module.exports = {
33
semi: false,
44
singleQuote: true,
55
trailingComma: 'all',
6+
pluginSearchDirs: false,
7+
plugins: ['@ianvs/prettier-plugin-sort-imports'],
8+
importOrder: ['^@', '^[a-zA-Z0-9-]+', '^[./]'],
69
}

src/config.js

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,8 @@ import { createContext as createContextFallback } from 'tailwindcss/lib/lib/setu
1010
import loadConfigFallback from 'tailwindcss/loadConfig'
1111
import resolveConfigFallback from 'tailwindcss/resolveConfig'
1212

13-
/**
14-
* @typedef {object} ContextContainer
15-
* @property {any} context
16-
* @property {() => any} generateRules
17-
* @property {any} tailwindConfig
18-
**/
19-
20-
/**
21-
* @typedef {object} PluginOptions
22-
* @property {string} [tailwindConfig]
23-
* @property {string} filepath
24-
**/
13+
/** @typedef {import('./types').ContextContainer} ContextContainer **/
14+
/** @typedef {import('./types').PluginOptions} PluginOptions **/
2515

2616
/**
2717
* @template K

0 commit comments

Comments
 (0)