Skip to content

Commit ea6f14a

Browse files
authored
Dedupe duplicate properties (#5830)
* add `collapseDuplicateDeclarations` This will allow us to remove duplicate declarations. This occurs when you are using `@apply` for example. The reason I implemented it as a separate step, is because this doesn't only happen for `@apply`, but it also happens if you do something like: ```js addComponents({ '.btn-blue, .btm-red': { padding: '10px' } }) ``` So instead of tracking down every place this is happening, it now happens at the very end. * use new plugin in processTailwindFeatures * add/update tests by removing duplicate declarations * update changelog
1 parent 0c2f1a6 commit ea6f14a

7 files changed

+58
-8
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2929
- Configure chokidar's `awaitWriteFinish` setting to avoid occasional stale builds on Windows ([#5774](https://github.com/tailwindlabs/tailwindcss/pull/5774))
3030
- Fix CLI `--content` option ([#5775](https://github.com/tailwindlabs/tailwindcss/pull/5775))
3131
- Fix before/after utilities overriding custom content values at larger breakpoints ([#5820](https://github.com/tailwindlabs/tailwindcss/pull/5820))
32+
- Cleanup duplicate properties ([#5830](https://github.com/tailwindlabs/tailwindcss/pull/5830))
3233

3334
## [3.0.0-alpha.1] - 2021-10-01
3435

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
export default function collapseDuplicateDeclarations() {
2+
return (root) => {
3+
root.walkRules((node) => {
4+
let seen = new Map()
5+
let droppable = new Set([])
6+
7+
node.walkDecls((decl) => {
8+
// This could happen if we have nested selectors. In that case the
9+
// parent will loop over all its declarations but also the declarations
10+
// of nested rules. With this we ensure that we are shallowly checking
11+
// declarations.
12+
if (decl.parent !== node) {
13+
return
14+
}
15+
16+
if (seen.has(decl.prop)) {
17+
droppable.add(seen.get(decl.prop))
18+
}
19+
20+
seen.set(decl.prop, decl)
21+
})
22+
23+
for (let decl of droppable) {
24+
decl.remove()
25+
}
26+
})
27+
}
28+
}

src/processTailwindFeatures.js

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import evaluateTailwindFunctions from './lib/evaluateTailwindFunctions'
55
import substituteScreenAtRules from './lib/substituteScreenAtRules'
66
import resolveDefaultsAtRules from './lib/resolveDefaultsAtRules'
77
import collapseAdjacentRules from './lib/collapseAdjacentRules'
8+
import collapseDuplicateDeclarations from './lib/collapseDuplicateDeclarations'
89
import detectNesting from './lib/detectNesting'
910
import { createContext } from './lib/setupContextUtils'
1011
import { issueFlagNotices } from './featureFlags'
@@ -42,5 +43,6 @@ export default function processTailwindFeatures(setupContext) {
4243
substituteScreenAtRules(context)(root, result)
4344
resolveDefaultsAtRules(context)(root, result)
4445
collapseAdjacentRules(context)(root, result)
46+
collapseDuplicateDeclarations(context)(root, result)
4547
}
4648
}

tests/apply.test.css

-4
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@
1010
.class-order {
1111
padding: 2rem;
1212
padding-left: 0.75rem;
13-
padding-right: 0.75rem;
14-
padding-top: 1.75rem;
1513
padding-bottom: 1.75rem;
1614
padding-top: 1rem;
1715
padding-right: 0.25rem;
@@ -127,7 +125,6 @@
127125
/* TODO: This works but the generated CSS is unnecessarily verbose. */
128126
.complex-utilities {
129127
--tw-ordinal: ordinal;
130-
font-variant-numeric: var(--tw-font-variant-numeric);
131128
--tw-numeric-spacing: tabular-nums;
132129
font-variant-numeric: var(--tw-font-variant-numeric);
133130
--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -2px rgb(0 0 0 / 0.05);
@@ -155,7 +152,6 @@
155152
font-weight: 700;
156153
}
157154
.use-dependant-only-b {
158-
font-weight: 700;
159155
font-weight: 400;
160156
}
161157
.btn {

tests/apply.test.js

+27-1
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,6 @@ test('@applying classes from outside a @layer respects the source order', async
351351
await run(input, config).then((result) => {
352352
return expect(result.css).toMatchFormattedCss(css`
353353
.baz {
354-
text-decoration: underline;
355354
text-decoration: none;
356355
}
357356
@@ -402,3 +401,30 @@ test('@applying classes from outside a @layer respects the source order', async
402401
`)
403402
})
404403
})
404+
405+
it('should remove duplicate properties when using apply with similar properties', () => {
406+
let config = {
407+
content: [{ raw: 'foo' }],
408+
}
409+
410+
let input = css`
411+
@tailwind utilities;
412+
413+
.foo {
414+
@apply absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2;
415+
}
416+
`
417+
418+
return run(input, config).then((result) => {
419+
expect(result.css).toMatchFormattedCss(css`
420+
.foo {
421+
position: absolute;
422+
top: 50%;
423+
left: 50%;
424+
--tw-translate-x: -50%;
425+
--tw-translate-y: -50%;
426+
transform: var(--tw-transform);
427+
}
428+
`)
429+
})
430+
})

tests/custom-plugins.test.js

-2
Original file line numberDiff line numberDiff line change
@@ -868,7 +868,6 @@ test('when important is a selector it scopes all selectors in a rule, even thoug
868868
#app .custom-rotate-90,
869869
#app .custom-rotate-1\/4 {
870870
transform: rotate(90deg);
871-
transform: rotate(90deg);
872871
}
873872
`)
874873
})
@@ -952,7 +951,6 @@ test('all selectors in a rule are prefixed', () => {
952951
.tw-btn-blue,
953952
.tw-btn-red {
954953
padding: 10px;
955-
padding: 10px;
956954
}
957955
`)
958956
})

tests/kitchen-sink.test.css

-1
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,6 @@ div {
199199
}
200200
.test-apply-font-variant {
201201
--tw-ordinal: ordinal;
202-
font-variant-numeric: var(--tw-font-variant-numeric);
203202
--tw-numeric-spacing: tabular-nums;
204203
font-variant-numeric: var(--tw-font-variant-numeric);
205204
}

0 commit comments

Comments
 (0)