Skip to content

Commit

Permalink
Dedupe duplicate properties (#5830)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
RobinMalfait committed Oct 21, 2021
1 parent 0c2f1a6 commit ea6f14a
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 8 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Configure chokidar's `awaitWriteFinish` setting to avoid occasional stale builds on Windows ([#5774](https://github.com/tailwindlabs/tailwindcss/pull/5774))
- Fix CLI `--content` option ([#5775](https://github.com/tailwindlabs/tailwindcss/pull/5775))
- Fix before/after utilities overriding custom content values at larger breakpoints ([#5820](https://github.com/tailwindlabs/tailwindcss/pull/5820))
- Cleanup duplicate properties ([#5830](https://github.com/tailwindlabs/tailwindcss/pull/5830))

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

Expand Down
28 changes: 28 additions & 0 deletions src/lib/collapseDuplicateDeclarations.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
export default function collapseDuplicateDeclarations() {
return (root) => {
root.walkRules((node) => {
let seen = new Map()
let droppable = new Set([])

node.walkDecls((decl) => {
// This could happen if we have nested selectors. In that case the
// parent will loop over all its declarations but also the declarations
// of nested rules. With this we ensure that we are shallowly checking
// declarations.
if (decl.parent !== node) {
return
}

if (seen.has(decl.prop)) {
droppable.add(seen.get(decl.prop))
}

seen.set(decl.prop, decl)
})

for (let decl of droppable) {
decl.remove()
}
})
}
}
2 changes: 2 additions & 0 deletions src/processTailwindFeatures.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import evaluateTailwindFunctions from './lib/evaluateTailwindFunctions'
import substituteScreenAtRules from './lib/substituteScreenAtRules'
import resolveDefaultsAtRules from './lib/resolveDefaultsAtRules'
import collapseAdjacentRules from './lib/collapseAdjacentRules'
import collapseDuplicateDeclarations from './lib/collapseDuplicateDeclarations'
import detectNesting from './lib/detectNesting'
import { createContext } from './lib/setupContextUtils'
import { issueFlagNotices } from './featureFlags'
Expand Down Expand Up @@ -42,5 +43,6 @@ export default function processTailwindFeatures(setupContext) {
substituteScreenAtRules(context)(root, result)
resolveDefaultsAtRules(context)(root, result)
collapseAdjacentRules(context)(root, result)
collapseDuplicateDeclarations(context)(root, result)
}
}
4 changes: 0 additions & 4 deletions tests/apply.test.css
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@
.class-order {
padding: 2rem;
padding-left: 0.75rem;
padding-right: 0.75rem;
padding-top: 1.75rem;
padding-bottom: 1.75rem;
padding-top: 1rem;
padding-right: 0.25rem;
Expand Down Expand Up @@ -127,7 +125,6 @@
/* TODO: This works but the generated CSS is unnecessarily verbose. */
.complex-utilities {
--tw-ordinal: ordinal;
font-variant-numeric: var(--tw-font-variant-numeric);
--tw-numeric-spacing: tabular-nums;
font-variant-numeric: var(--tw-font-variant-numeric);
--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -2px rgb(0 0 0 / 0.05);
Expand Down Expand Up @@ -155,7 +152,6 @@
font-weight: 700;
}
.use-dependant-only-b {
font-weight: 700;
font-weight: 400;
}
.btn {
Expand Down
28 changes: 27 additions & 1 deletion tests/apply.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,6 @@ test('@applying classes from outside a @layer respects the source order', async
await run(input, config).then((result) => {
return expect(result.css).toMatchFormattedCss(css`
.baz {
text-decoration: underline;
text-decoration: none;
}
Expand Down Expand Up @@ -402,3 +401,30 @@ test('@applying classes from outside a @layer respects the source order', async
`)
})
})

it('should remove duplicate properties when using apply with similar properties', () => {
let config = {
content: [{ raw: 'foo' }],
}

let input = css`
@tailwind utilities;
.foo {
@apply absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2;
}
`

return run(input, config).then((result) => {
expect(result.css).toMatchFormattedCss(css`
.foo {
position: absolute;
top: 50%;
left: 50%;
--tw-translate-x: -50%;
--tw-translate-y: -50%;
transform: var(--tw-transform);
}
`)
})
})
2 changes: 0 additions & 2 deletions tests/custom-plugins.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -868,7 +868,6 @@ test('when important is a selector it scopes all selectors in a rule, even thoug
#app .custom-rotate-90,
#app .custom-rotate-1\/4 {
transform: rotate(90deg);
transform: rotate(90deg);
}
`)
})
Expand Down Expand Up @@ -952,7 +951,6 @@ test('all selectors in a rule are prefixed', () => {
.tw-btn-blue,
.tw-btn-red {
padding: 10px;
padding: 10px;
}
`)
})
Expand Down
1 change: 0 additions & 1 deletion tests/kitchen-sink.test.css
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,6 @@ div {
}
.test-apply-font-variant {
--tw-ordinal: ordinal;
font-variant-numeric: var(--tw-font-variant-numeric);
--tw-numeric-spacing: tabular-nums;
font-variant-numeric: var(--tw-font-variant-numeric);
}
Expand Down

0 comments on commit ea6f14a

Please sign in to comment.