Fix sorting of utilities that share multiple candidates (#12173)
* Fix sorting of utilities that share multiple candidates * Update changelog
This commit is contained in:
parent
f57c2f90d8
commit
58b126f0d8
4 changed files with 45 additions and 3 deletions
|
|
@ -24,6 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- Don’t crash when important and parent selectors are equal in `@apply` ([#12112](https://github.com/tailwindlabs/tailwindcss/pull/12112))
|
||||
- Eliminate irrelevant rules when applying variants ([#12113](https://github.com/tailwindlabs/tailwindcss/pull/12113))
|
||||
- Improve RegEx parser, reduce possibilities as the key for arbitrary properties ([#12121](https://github.com/tailwindlabs/tailwindcss/pull/12121))
|
||||
- Fix sorting of utilities that share multiple candidates ([#12173](https://github.com/tailwindlabs/tailwindcss/pull/12173))
|
||||
|
||||
## [3.3.3] - 2023-07-13
|
||||
|
||||
|
|
|
|||
|
|
@ -882,7 +882,7 @@ function getImportantStrategy(important) {
|
|||
}
|
||||
}
|
||||
|
||||
function generateRules(candidates, context) {
|
||||
function generateRules(candidates, context, isSorting = false) {
|
||||
let allRules = []
|
||||
let strategy = getImportantStrategy(context.tailwindConfig.important)
|
||||
|
||||
|
|
@ -917,7 +917,9 @@ function generateRules(candidates, context) {
|
|||
rule = container.nodes[0]
|
||||
}
|
||||
|
||||
let newEntry = [sort, rule]
|
||||
// Note: We have to clone rules during sorting
|
||||
// so we eliminate some shared mutable state
|
||||
let newEntry = [sort, isSorting ? rule.clone() : rule]
|
||||
rules.add(newEntry)
|
||||
context.ruleCache.add(newEntry)
|
||||
allRules.push(newEntry)
|
||||
|
|
|
|||
|
|
@ -947,7 +947,7 @@ function registerPlugins(plugins, context) {
|
|||
|
||||
// Sort all classes in order
|
||||
// Non-tailwind classes won't be generated and will be left as `null`
|
||||
let rules = generateRules(new Set(sorted), context)
|
||||
let rules = generateRules(new Set(sorted), context, true)
|
||||
rules = context.offsets.sort(rules)
|
||||
|
||||
let idx = BigInt(parasiteUtilities.length)
|
||||
|
|
|
|||
|
|
@ -181,3 +181,42 @@ it('sorts based on first occurence of a candidate / rule', () => {
|
|||
expect(defaultSort(context.getClassOrder(input.split(' ')))).toEqual(output)
|
||||
}
|
||||
})
|
||||
|
||||
it('Sorting is unchanged when multiple candidates share the same rule / object', () => {
|
||||
let classes = [
|
||||
['x y', 'x y'],
|
||||
['a', 'a'],
|
||||
['x y', 'x y'],
|
||||
]
|
||||
|
||||
let config = {
|
||||
theme: {},
|
||||
plugins: [
|
||||
function ({ addComponents }) {
|
||||
addComponents({
|
||||
'.x': { color: 'red' },
|
||||
'.a': { color: 'red' },
|
||||
|
||||
// This rule matches both the candidate `a` and `y`
|
||||
// When sorting x and y first we would keep that sort order
|
||||
// Then sorting `a` we would end up replacing the candidate on the rule
|
||||
// Thus causing `y` to no longer have a sort order causing it to be sorted
|
||||
// first by accident
|
||||
'.y .a': { color: 'red' },
|
||||
})
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
// 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…
Add table
Add a link
Reference in a new issue