diff --git a/CHANGELOG.md b/CHANGELOG.md index 41ecdba06..989a47d7b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -58,6 +58,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Don't require `content` key in custom plugin configs ([#9502](https://github.com/tailwindlabs/tailwindcss/pull/9502), [#9545](https://github.com/tailwindlabs/tailwindcss/pull/9545)) - Fix content path detection on Windows ([#9569](https://github.com/tailwindlabs/tailwindcss/pull/9569)) - Ensure `--content` is used in the CLI when passed ([#9587](https://github.com/tailwindlabs/tailwindcss/pull/9587)) +- Increase strictness when using `applyVariant` on illegale candidates ([#9599](https://github.com/tailwindlabs/tailwindcss/pull/9599)) ## [3.1.8] - 2022-08-05 diff --git a/src/lib/generateRules.js b/src/lib/generateRules.js index d56427896..8b1c2843f 100644 --- a/src/lib/generateRules.js +++ b/src/lib/generateRules.js @@ -162,10 +162,23 @@ function applyVariant(variant, matches, context) { // Retrieve "arbitrary value" if (variant.endsWith(']') && !variant.startsWith('[')) { - let match = /-?\[(.*)\]/g.exec(variant) + // We either have: + // @[200px] + // group-[:hover] + // + // But we don't want: + // @-[200px] (`-` is incorrect) + // group[:hover] (`-` is missing) + let match = /(.)(-?)\[(.*)\]/g.exec(variant) if (match) { - variant = variant.replace(match[0], '') - args.value = match[1] + let [, char, seperator, value] = match + // @-[200px] case + if (char === '@' && seperator === '-') return [] + // group[:hover] case + if (char !== '@' && seperator === '') return [] + + variant = variant.replace(`${seperator}[${value}]`, '') + args.value = value } } diff --git a/tests/generate-rules.test.js b/tests/generate-rules.test.js new file mode 100644 index 000000000..a997a46cd --- /dev/null +++ b/tests/generate-rules.test.js @@ -0,0 +1,47 @@ +import { css } from './util/run' + +import { generateRules } from '../src/lib/generateRules' +import resolveConfig from '../src/public/resolve-config' +import { createContext } from '../src/lib/setupContextUtils' + +it('should not generate rules that are incorrect', () => { + let config = { + plugins: [ + ({ matchVariant }) => { + matchVariant('@', (value) => `@container (min-width: ${value})`) + }, + ], + } + let context = createContext(resolveConfig(config)) + let rules = generateRules( + new Set([ + // Invalid, missing `-` + 'group[:hover]:underline', + + // Invalid, `-` should not be there + '@-[200px]:underline', + + // Valid + 'group-[:hover]:underline', + '@[200px]:underline', + ]), + context + ) + + // Ensure we only have 2 valid rules + expect(rules).toHaveLength(2) + + // Ensure we have the correct values + expect(rules[0][1].toString()).toMatchFormattedCss(css` + .group:hover .group-\[\:hover\]\:underline { + text-decoration-line: underline; + } + `) + expect(rules[1][1].toString()).toMatchFormattedCss(css` + @container (min-width: 200px) { + .\@\[200px\]\:underline { + text-decoration-line: underline; + } + } + `) +})