Fix defaults optimization when vendor prefixes are involved (#6369)

This commit is contained in:
Jordan Pittman 2021-12-10 10:45:33 -05:00 committed by GitHub
parent 08241c3f75
commit 429fe07a5f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 68 additions and 7 deletions

View File

@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Ensure complex variants with multiple classes work ([#6311](https://github.com/tailwindlabs/tailwindcss/pull/6311))
- Re-add `default` interop to public available functions ([#6348](https://github.com/tailwindlabs/tailwindcss/pull/6348))
- Detect circular dependencies when using `@apply` ([#6365](https://github.com/tailwindlabs/tailwindcss/pull/6365))
- Fix defaults optimization when vendor prefixes are involved ([#6369](https://github.com/tailwindlabs/tailwindcss/pull/6369))
## [3.0.0] - 2021-12-09

View File

@ -71,6 +71,8 @@ function extractElementSelector(selector) {
export default function resolveDefaultsAtRules({ tailwindConfig }) {
return (root) => {
let variableNodeMap = new Map()
/** @type {Set<import('postcss').AtRule>} */
let universals = new Set()
root.walkAtRules('defaults', (rule) => {
@ -90,31 +92,50 @@ export default function resolveDefaultsAtRules({ tailwindConfig }) {
})
for (let universal of universals) {
let selectors = new Set()
/** @type {Map<string, Set<string>>} */
let selectorGroups = new Map()
let rules = variableNodeMap.get(universal.params) ?? []
for (let rule of rules) {
for (let selector of extractElementSelector(rule.selector)) {
// If selector contains a vendor prefix after a pseudo element or class,
// we consider them separately because merging the declarations into
// a single rule will cause browsers that do not understand the
// vendor prefix to throw out the whole rule
let selectorGroupName =
selector.includes(':-') || selector.includes('::-') ? selector : '__DEFAULT__'
let selectors = selectorGroups.get(selectorGroupName) ?? new Set()
selectorGroups.set(selectorGroupName, selectors)
selectors.add(selector)
}
}
if (selectors.size === 0) {
if (selectorGroups.size === 0) {
universal.remove()
continue
}
let universalRule = postcss.rule()
if (flagEnabled(tailwindConfig, 'optimizeUniversalDefaults')) {
universalRule.selectors = [...selectors]
for (let [, selectors] of selectorGroups) {
let universalRule = postcss.rule()
universalRule.selectors = [...selectors]
universalRule.append(universal.nodes.map((node) => node.clone()))
universal.before(universalRule)
}
} else {
let universalRule = postcss.rule()
universalRule.selectors = ['*', '::before', '::after']
universalRule.append(universal.nodes)
universal.before(universalRule)
}
universalRule.append(universal.nodes)
universal.before(universalRule)
universal.remove()
}
}

View File

@ -577,3 +577,42 @@ it('should throw when trying to apply an indirect circular dependency with a mod
expect(err.reason).toBe('Circular dependency detected when using: `@apply a`')
})
})
it('rules with vendor prefixes are still separate when optimizing defaults rules', () => {
let config = {
experimental: { optimizeUniversalDefaults: true },
content: [{ raw: html`<div class="border"></div>` }],
corePlugins: { preflight: false },
}
let input = css`
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer components {
input[type='range']::-moz-range-thumb {
@apply border;
}
}
`
return run(input, config).then((result) => {
return expect(result.css).toMatchFormattedCss(css`
[type='range']::-moz-range-thumb {
--tw-border-opacity: 1;
border-color: rgb(229 231 235 / var(--tw-border-opacity));
}
.border {
--tw-border-opacity: 1;
border-color: rgb(229 231 235 / var(--tw-border-opacity));
}
input[type='range']::-moz-range-thumb {
border-width: 1px;
}
.border {
border-width: 1px;
}
`)
})
})