diff --git a/CHANGELOG.md b/CHANGELOG.md index 07d169b08e72..f6b1d39be82a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Warn about invalid globs in `content` ([#6449](https://github.com/tailwindlabs/tailwindcss/pull/6449)) +### Fixed + +- Don't output unparsable values ([#6469](https://github.com/tailwindlabs/tailwindcss/pull/6469)) + ## [3.0.2] - 2021-12-13 ### Fixed diff --git a/src/lib/generateRules.js b/src/lib/generateRules.js index 521b35025e4a..806a70747e63 100644 --- a/src/lib/generateRules.js +++ b/src/lib/generateRules.js @@ -248,6 +248,21 @@ function parseRules(rule, cache, options = {}) { return [cache.get(rule), options] } +const IS_VALID_PROPERTY_NAME = /^[a-z_-]/ + +function isValidPropName(name) { + return IS_VALID_PROPERTY_NAME.test(name) +} + +function isParsableCssValue(property, value) { + try { + postcss.parse(`a{${property}:${value}}`).toResult() + return true + } catch (err) { + return false + } +} + function extractArbitraryProperty(classCandidate, context) { let [, property, value] = classCandidate.match(/^\[([a-zA-Z0-9-_]+):(\S+)\]$/) ?? [] @@ -255,9 +270,17 @@ function extractArbitraryProperty(classCandidate, context) { return null } + if (!isValidPropName(property)) { + return null + } + + if (!isValidArbitraryValue(value)) { + return null + } + let normalized = normalize(value) - if (!isValidArbitraryValue(normalized)) { + if (!isParsableCssValue(property, normalized)) { return null } diff --git a/tests/arbitrary-properties.test.js b/tests/arbitrary-properties.test.js index 574d1184072e..7ff008ce4819 100644 --- a/tests/arbitrary-properties.test.js +++ b/tests/arbitrary-properties.test.js @@ -231,3 +231,45 @@ test('invalid class', () => { expect(result.css).toMatchFormattedCss(css``) }) }) + +test('invalid arbitrary property', () => { + let config = { + content: [ + { + raw: html`
`, + }, + ], + corePlugins: { preflight: false }, + } + + let input = css` + @tailwind base; + @tailwind components; + @tailwind utilities; + ` + + return run(input, config).then((result) => { + expect(result.css).toMatchFormattedCss(css``) + }) +}) + +test('invalid arbitrary property 2', () => { + let config = { + content: [ + { + raw: html`[0:02]`, + }, + ], + corePlugins: { preflight: false }, + } + + let input = css` + @tailwind base; + @tailwind components; + @tailwind utilities; + ` + + return run(input, config).then((result) => { + expect(result.css).toMatchFormattedCss(css``) + }) +})