mirror of
https://github.com/tailwindlabs/tailwindcss.git
synced 2025-12-08 21:36:08 +00:00
Sort class lists deterministically for Prettier plugin (#10672)
* Ensure class sorting is deterministic for Prettier * Update changelog
This commit is contained in:
parent
261a8b42cb
commit
d2a95a00a8
@ -22,6 +22,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
### Fixed
|
||||
|
||||
- Disallow multiple selectors in arbitrary variants ([#10655](https://github.com/tailwindlabs/tailwindcss/pull/10655))
|
||||
- Sort class lists deterministically for Prettier plugin ([#10672](https://github.com/tailwindlabs/tailwindcss/pull/10672))
|
||||
|
||||
### Changed
|
||||
|
||||
|
||||
@ -931,12 +931,19 @@ function registerPlugins(plugins, context) {
|
||||
prefix(context, 'peer'),
|
||||
]
|
||||
context.getClassOrder = function getClassOrder(classes) {
|
||||
// Sort classes so they're ordered in a deterministic manner
|
||||
let sorted = [...classes].sort((a, z) => {
|
||||
if (a === z) return 0
|
||||
if (a < z) return -1
|
||||
return 1
|
||||
})
|
||||
|
||||
// Non-util classes won't be generated, so we default them to null
|
||||
let sortedClassNames = new Map(classes.map((className) => [className, null]))
|
||||
let sortedClassNames = new Map(sorted.map((className) => [className, null]))
|
||||
|
||||
// Sort all classes in order
|
||||
// Non-tailwind classes won't be generated and will be left as `null`
|
||||
let rules = generateRules(new Set(classes), context)
|
||||
let rules = generateRules(new Set(sorted), context)
|
||||
rules = context.offsets.sort(rules)
|
||||
|
||||
let idx = BigInt(parasiteUtilities.length)
|
||||
|
||||
@ -51,7 +51,7 @@ crosscheck(() => {
|
||||
['px-3 focus:hover:p-3 hover:p-1 py-3', 'px-3 py-3 hover:p-1 focus:hover:p-3'],
|
||||
|
||||
// Utitlies with important
|
||||
['px-3 !py-4', 'px-3 !py-4'],
|
||||
['px-3 !py-4', '!py-4 px-3'],
|
||||
['!py-4 px-3', '!py-4 px-3'],
|
||||
|
||||
// Components with variants
|
||||
@ -89,7 +89,7 @@ crosscheck(() => {
|
||||
],
|
||||
|
||||
// Utitlies with important
|
||||
['tw-px-3 !tw-py-4', 'tw-px-3 !tw-py-4'],
|
||||
['tw-px-3 !tw-py-4', '!tw-py-4 tw-px-3'],
|
||||
['!tw-py-4 tw-px-3', '!tw-py-4 tw-px-3'],
|
||||
|
||||
// Components with variants
|
||||
@ -115,4 +115,31 @@ crosscheck(() => {
|
||||
expect(defaultSort(context.getClassOrder(input.split(' ')))).toEqual(output)
|
||||
}
|
||||
)
|
||||
|
||||
it('sorts classes deterministically across multiple class lists', () => {
|
||||
let classes = [
|
||||
[
|
||||
'a-class px-3 p-1 b-class py-3 bg-red-500 bg-blue-500',
|
||||
'a-class b-class bg-blue-500 bg-red-500 p-1 px-3 py-3',
|
||||
],
|
||||
[
|
||||
'px-3 b-class p-1 py-3 bg-blue-500 a-class bg-red-500',
|
||||
'b-class a-class bg-blue-500 bg-red-500 p-1 px-3 py-3',
|
||||
],
|
||||
]
|
||||
|
||||
let config = {}
|
||||
|
||||
// Same context, different class lists
|
||||
let context = createContext(resolveConfig(config))
|
||||
for (const [input, output] of classes) {
|
||||
expect(defaultSort(context.getClassOrder(input.split(' ')))).toEqual(output)
|
||||
}
|
||||
|
||||
// Different context, different class lists
|
||||
for (const [input, output] of classes) {
|
||||
context = createContext(resolveConfig(config))
|
||||
expect(defaultSort(context.getClassOrder(input.split(' ')))).toEqual(output)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user