Skip to content

Commit 15dc5a3

Browse files
Remove text opacity CSS variables from ::marker (#8622)
* Refactor * Allow parallel variant fns to mutate the container * Remove text color variable from marker pseudo class wip * Update changelog
1 parent 22eaad1 commit 15dc5a3

File tree

7 files changed

+115
-32
lines changed

7 files changed

+115
-32
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1515
- Fix missing spaces around arithmetic operators ([#8615](https://github.com/tailwindlabs/tailwindcss/pull/8615))
1616
- Detect alpha value in CSS `theme()` function when using quotes ([#8625](https://github.com/tailwindlabs/tailwindcss/pull/8625))
1717
- Fix "Maximum call stack size exceeded" bug ([#8636](https://github.com/tailwindlabs/tailwindcss/pull/8636))
18+
- Allow functions returning parallel variants to mutate the container ([#8622](https://github.com/tailwindlabs/tailwindcss/pull/8622))
19+
- Remove text opacity CSS variables from `::marker` ([#8622](https://github.com/tailwindlabs/tailwindcss/pull/8622))
1820

1921
## [3.1.2] - 2022-06-10
2022

src/corePlugins.js

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,27 @@ import { version as tailwindVersion } from '../package.json'
1414
import log from './util/log'
1515
import { normalizeScreens } from './util/normalizeScreens'
1616
import { formatBoxShadowValue, parseBoxShadowValue } from './util/parseBoxShadowValue'
17+
import { removeAlphaVariables } from './util/removeAlphaVariables'
1718
import { flagEnabled } from './featureFlags'
1819

1920
export let variantPlugins = {
2021
pseudoElementVariants: ({ addVariant }) => {
2122
addVariant('first-letter', '&::first-letter')
2223
addVariant('first-line', '&::first-line')
2324

24-
addVariant('marker', ['& *::marker', '&::marker'])
25+
addVariant('marker', [
26+
({ container }) => {
27+
removeAlphaVariables(container, ['--tw-text-opacity'])
28+
29+
return '& *::marker'
30+
},
31+
({ container }) => {
32+
removeAlphaVariables(container, ['--tw-text-opacity'])
33+
34+
return '&::marker'
35+
},
36+
])
37+
2538
addVariant('selection', ['& *::selection', '&::selection'])
2639

2740
addVariant('file', '&::file-selector-button')
@@ -77,21 +90,11 @@ export let variantPlugins = {
7790
[
7891
'visited',
7992
({ container }) => {
80-
let toRemove = ['--tw-text-opacity', '--tw-border-opacity', '--tw-bg-opacity']
81-
82-
container.walkDecls((decl) => {
83-
if (toRemove.includes(decl.prop)) {
84-
decl.remove()
85-
86-
return
87-
}
88-
89-
for (const varName of toRemove) {
90-
if (decl.value.includes(`/ var(${varName})`)) {
91-
decl.value = decl.value.replace(`/ var(${varName})`, '')
92-
}
93-
}
94-
})
93+
removeAlphaVariables(container, [
94+
'--tw-text-opacity',
95+
'--tw-border-opacity',
96+
'--tw-bg-opacity',
97+
])
9598

9699
return '&:visited'
97100
},

src/lib/generateRules.js

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -163,15 +163,17 @@ function applyVariant(variant, matches, context) {
163163

164164
let container = postcss.root({ nodes: [rule.clone()] })
165165

166-
for (let [variantSort, variantFunction] of variantFunctionTuples) {
167-
let clone = container.clone()
166+
for (let [variantSort, variantFunction, containerFromArray] of variantFunctionTuples) {
167+
let clone = containerFromArray ?? container.clone()
168168
let collectedFormats = []
169169

170-
let originals = new Map()
171-
172170
function prepareBackup() {
173-
if (originals.size > 0) return // Already prepared, chicken out
174-
clone.walkRules((rule) => originals.set(rule, rule.selector))
171+
// Already prepared, chicken out
172+
if (clone.raws.neededBackup) {
173+
return
174+
}
175+
clone.raws.neededBackup = true
176+
clone.walkRules((rule) => (rule.raws.originalSelector = rule.selector))
175177
}
176178

177179
function modifySelectors(modifierFunction) {
@@ -231,6 +233,10 @@ function applyVariant(variant, matches, context) {
231233
// reserving additional X places for these 'unknown' variants in between.
232234
variantSort | BigInt(idx << ruleWithVariant.length),
233235
variantFunction,
236+
237+
// If the clone has been modified we have to pass that back
238+
// though so each rule can use the modified container
239+
clone.clone(),
234240
])
235241
}
236242
continue
@@ -244,13 +250,15 @@ function applyVariant(variant, matches, context) {
244250
continue
245251
}
246252

247-
// We filled the `originals`, therefore we assume that somebody touched
253+
// We had to backup selectors, therefore we assume that somebody touched
248254
// `container` or `modifySelectors`. Let's see if they did, so that we
249255
// can restore the selectors, and collect the format strings.
250-
if (originals.size > 0) {
256+
if (clone.raws.neededBackup) {
257+
delete clone.raws.neededBackup
251258
clone.walkRules((rule) => {
252-
if (!originals.has(rule)) return
253-
let before = originals.get(rule)
259+
let before = rule.raws.originalSelector
260+
if (!before) return
261+
delete rule.raws.originalSelector
254262
if (before === rule.selector) return // No mutation happened
255263

256264
let modified = rule.selector

src/util/removeAlphaVariables.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/**
2+
* This function removes any uses of CSS variables used as an alpha channel
3+
*
4+
* This is required for selectors like `:visited` which do not allow
5+
* changes in opacity or external control using CSS variables.
6+
*
7+
* @param {import('postcss').Container} container
8+
* @param {string[]} toRemove
9+
*/
10+
export function removeAlphaVariables(container, toRemove) {
11+
container.walkDecls((decl) => {
12+
if (toRemove.includes(decl.prop)) {
13+
decl.remove()
14+
15+
return
16+
}
17+
18+
for (let varName of toRemove) {
19+
if (decl.value.includes(`/ var(${varName})`)) {
20+
decl.value = decl.value.replace(`/ var(${varName})`, '')
21+
}
22+
}
23+
})
24+
}

tests/parallel-variants.test.js

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,3 +85,52 @@ test('parallel variants can be generated using a function that returns parallel
8585
`)
8686
})
8787
})
88+
89+
test('a function that returns parallel variants can modify the container', async () => {
90+
let config = {
91+
content: [
92+
{
93+
raw: html`<div
94+
class="hover:test:font-black test:font-bold test:font-medium font-normal"
95+
></div>`,
96+
},
97+
],
98+
plugins: [
99+
function test({ addVariant }) {
100+
addVariant('test', ({ container }) => {
101+
container.walkDecls((decl) => {
102+
decl.value = `calc(0 + ${decl.value})`
103+
})
104+
105+
return ['& *::test', '&::test']
106+
})
107+
},
108+
],
109+
}
110+
111+
return run('@tailwind utilities', config).then((result) => {
112+
expect(result.css).toMatchFormattedCss(css`
113+
.font-normal {
114+
font-weight: 400;
115+
}
116+
.test\:font-bold *::test {
117+
font-weight: calc(0 + 700);
118+
}
119+
.test\:font-medium *::test {
120+
font-weight: calc(0 + 500);
121+
}
122+
.test\:font-bold::test {
123+
font-weight: calc(0 + 700);
124+
}
125+
.test\:font-medium::test {
126+
font-weight: calc(0 + 500);
127+
}
128+
.hover\:test\:font-black *:hover::test {
129+
font-weight: calc(0 + 900);
130+
}
131+
.hover\:test\:font-black:hover::test {
132+
font-weight: calc(0 + 900);
133+
}
134+
`)
135+
})
136+
})

tests/variants.test.css

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,16 +112,14 @@
112112
line-height: 1.75rem;
113113
}
114114
.marker\:text-red-500 *::marker {
115-
--tw-text-opacity: 1;
116-
color: rgb(239 68 68 / var(--tw-text-opacity));
115+
color: rgb(239 68 68);
117116
}
118117
.marker\:text-lg::marker {
119118
font-size: 1.125rem;
120119
line-height: 1.75rem;
121120
}
122121
.marker\:text-red-500::marker {
123-
--tw-text-opacity: 1;
124-
color: rgb(239 68 68 / var(--tw-text-opacity));
122+
color: rgb(239 68 68);
125123
}
126124
.selection\:bg-blue-500 *::selection {
127125
--tw-bg-opacity: 1;

tests/variants.test.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -485,8 +485,7 @@ test('returning non-strings and non-selectors in addVariant', () => {
485485

486486
addVariant('peer-aria-expanded-2', ({ modifySelectors, separator }) => {
487487
let nodes = modifySelectors(
488-
({ className }) =>
489-
`.peer[aria-expanded="false"] ~ .${e(`peer-aria-expanded${separator}${className}`)}`
488+
({ className }) => `.${e(`peer-aria-expanded-2${separator}${className}`)}`
490489
)
491490

492491
return [

0 commit comments

Comments
 (0)