Skip to content

Commit 684f7f1

Browse files
committed
allow for nested addVariant shorthand
This will allow to write something like: ```js addVariant('name', ` @supports (hover: hover) { @media (print) { &:hover } } `) // Or as a one-liner addVariant('name', '@supports (hover: hover) { @media (print) { &:hover } }') ```
1 parent 2e8ea0f commit 684f7f1

File tree

2 files changed

+76
-5
lines changed

2 files changed

+76
-5
lines changed

src/lib/setupContextUtils.js

+49-5
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,35 @@ import { toPath } from '../util/toPath'
1919
import log from '../util/log'
2020
import negateValue from '../util/negateValue'
2121

22+
function parseVariantFormatString(input) {
23+
if (input.includes('{')) {
24+
if (!isBalanced(input)) throw new Error(`Your { and } are unbalanced.`)
25+
26+
return input
27+
.split(/{(.*)}/gim)
28+
.flatMap((line) => parseVariantFormatString(line))
29+
.filter(Boolean)
30+
}
31+
32+
return [input.trim()]
33+
}
34+
35+
function isBalanced(input) {
36+
let count = 0
37+
38+
for (let char of input) {
39+
if (char === '{') {
40+
count++
41+
} else if (char === '}') {
42+
if (--count < 0) {
43+
return false // unbalanced
44+
}
45+
}
46+
}
47+
48+
return count === 0
49+
}
50+
2251
function insertInto(list, value, { before = [] } = {}) {
2352
before = [].concat(before)
2453

@@ -191,12 +220,27 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
191220
return variantFunction
192221
}
193222

194-
if (!variantFunction.startsWith('@')) {
195-
return ({ format }) => format(variantFunction)
196-
}
223+
variantFunction = variantFunction
224+
.replace(/\n+/g, '')
225+
.replace(/\s{1,}/g, ' ')
226+
.trim()
227+
228+
let fns = parseVariantFormatString(variantFunction)
229+
.map((str) => {
230+
if (!str.startsWith('@')) {
231+
return ({ format }) => format(str)
232+
}
233+
234+
let [, name, params] = /@(.*?) (\(.*\))/g.exec(str)
235+
return ({ wrap }) => wrap(postcss.atRule({ name, params }))
236+
})
237+
.reverse()
197238

198-
let [, name, params] = /@(.*?) (\(.*\))/g.exec(variantFunction)
199-
return ({ wrap }) => wrap(postcss.atRule({ name, params }))
239+
return (api) => {
240+
for (let fn of fns) {
241+
fn(api)
242+
}
243+
}
200244
})
201245

202246
insertInto(variantList, variantName, options)

tests/variants.test.js

+27
Original file line numberDiff line numberDiff line change
@@ -244,3 +244,30 @@ it('should properly handle keyframes with multiple variants', async () => {
244244
}
245245
`)
246246
})
247+
248+
test('custom addVariant with nested media & format shorthand', () => {
249+
let config = {
250+
content: [
251+
{
252+
raw: html` <div class="magic:text-center"></div> `,
253+
},
254+
],
255+
plugins: [
256+
function ({ addVariant }) {
257+
addVariant('magic', '@supports (hover: hover) { @media (print) { &:disabled } }')
258+
},
259+
],
260+
}
261+
262+
return run('@tailwind components;@tailwind utilities', config).then((result) => {
263+
return expect(result.css).toMatchFormattedCss(css`
264+
@supports (hover: hover) {
265+
@media (print) {
266+
.magic\\:text-center:disabled {
267+
text-align: center;
268+
}
269+
}
270+
}
271+
`)
272+
})
273+
})

0 commit comments

Comments
 (0)