From c99a7ded94fb785d89f9b2736d84334ccd1e6b48 Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Thu, 23 Feb 2023 13:10:47 -0500 Subject: [PATCH 1/2] Ensure class sorting is deterministic for Prettier --- src/lib/setupContextUtils.js | 11 +++++++++-- tests/getSortOrder.test.js | 31 +++++++++++++++++++++++++++++-- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/src/lib/setupContextUtils.js b/src/lib/setupContextUtils.js index 9a140096e556..0749da68dbdc 100644 --- a/src/lib/setupContextUtils.js +++ b/src/lib/setupContextUtils.js @@ -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) diff --git a/tests/getSortOrder.test.js b/tests/getSortOrder.test.js index b65e447d1f35..4526c4874f69 100644 --- a/tests/getSortOrder.test.js +++ b/tests/getSortOrder.test.js @@ -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) + } + }) }) From e44eafa9db38740e6df92274e46e45a8a419b727 Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Thu, 23 Feb 2023 13:17:03 -0500 Subject: [PATCH 2/2] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c4d96da84e49..449ccc635fa1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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