Skip to content

Commit

Permalink
allow for nested addVariant shorthand
Browse files Browse the repository at this point in the history
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 } }')
```
  • Loading branch information
RobinMalfait committed Oct 17, 2021
1 parent 2e8ea0f commit 684f7f1
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 5 deletions.
54 changes: 49 additions & 5 deletions src/lib/setupContextUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,35 @@ import { toPath } from '../util/toPath'
import log from '../util/log'
import negateValue from '../util/negateValue'

function parseVariantFormatString(input) {
if (input.includes('{')) {
if (!isBalanced(input)) throw new Error(`Your { and } are unbalanced.`)

return input
.split(/{(.*)}/gim)
.flatMap((line) => parseVariantFormatString(line))
.filter(Boolean)
}

return [input.trim()]
}

function isBalanced(input) {
let count = 0

for (let char of input) {
if (char === '{') {
count++
} else if (char === '}') {
if (--count < 0) {
return false // unbalanced
}
}
}

return count === 0
}

function insertInto(list, value, { before = [] } = {}) {
before = [].concat(before)

Expand Down Expand Up @@ -191,12 +220,27 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
return variantFunction
}

if (!variantFunction.startsWith('@')) {
return ({ format }) => format(variantFunction)
}
variantFunction = variantFunction
.replace(/\n+/g, '')
.replace(/\s{1,}/g, ' ')
.trim()

let fns = parseVariantFormatString(variantFunction)
.map((str) => {
if (!str.startsWith('@')) {
return ({ format }) => format(str)
}

let [, name, params] = /@(.*?) (\(.*\))/g.exec(str)
return ({ wrap }) => wrap(postcss.atRule({ name, params }))
})
.reverse()

let [, name, params] = /@(.*?) (\(.*\))/g.exec(variantFunction)
return ({ wrap }) => wrap(postcss.atRule({ name, params }))
return (api) => {
for (let fn of fns) {
fn(api)
}
}
})

insertInto(variantList, variantName, options)
Expand Down
27 changes: 27 additions & 0 deletions tests/variants.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -244,3 +244,30 @@ it('should properly handle keyframes with multiple variants', async () => {
}
`)
})

test('custom addVariant with nested media & format shorthand', () => {
let config = {
content: [
{
raw: html` <div class="magic:text-center"></div> `,
},
],
plugins: [
function ({ addVariant }) {
addVariant('magic', '@supports (hover: hover) { @media (print) { &:disabled } }')
},
],
}

return run('@tailwind components;@tailwind utilities', config).then((result) => {
return expect(result.css).toMatchFormattedCss(css`
@supports (hover: hover) {
@media (print) {
.magic\\:text-center:disabled {
text-align: center;
}
}
}
`)
})
})

0 comments on commit 684f7f1

Please sign in to comment.