diff --git a/CHANGELOG.md b/CHANGELOG.md index 40ae653bfb5e..d0cb726bfac4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix before/after utilities overriding custom content values at larger breakpoints ([#5820](https://github.com/tailwindlabs/tailwindcss/pull/5820)) - Cleanup duplicate properties ([#5830](https://github.com/tailwindlabs/tailwindcss/pull/5830)) - Allow `_` inside `url()` when using arbitrary values ([#5853](https://github.com/tailwindlabs/tailwindcss/pull/5853)) +- Prevent crashes when using comments in `@layer` AtRules ([#5854](https://github.com/tailwindlabs/tailwindcss/pull/5854)) ## [3.0.0-alpha.1] - 2021-10-01 diff --git a/src/lib/generateRules.js b/src/lib/generateRules.js index 85fd44e82042..cdb5294769f6 100644 --- a/src/lib/generateRules.js +++ b/src/lib/generateRules.js @@ -448,28 +448,42 @@ function generateRules(candidates, context) { allRules.push(matches) } - return allRules.flat(1).map(([{ sort, layer, options }, rule]) => { - if (options.respectImportant) { - if (context.tailwindConfig.important === true) { + // Strategy based on `tailwindConfig.important` + let strategy = ((important) => { + if (important === true) { + return (rule) => { rule.walkDecls((d) => { if (d.parent.type === 'rule' && !inKeyframes(d.parent)) { d.important = true } }) - } else if (typeof context.tailwindConfig.important === 'string') { + } + } + + if (typeof important === 'string') { + return (rule) => { + rule.selectors = rule.selectors.map((selector) => { + return `${important} ${selector}` + }) + } + } + })(context.tailwindConfig.important) + + return allRules.flat(1).map(([{ sort, layer, options }, rule]) => { + if (options.respectImportant) { + if (strategy) { let container = postcss.root({ nodes: [rule.clone()] }) container.walkRules((r) => { if (inKeyframes(r)) { return } - r.selectors = r.selectors.map((selector) => { - return `${context.tailwindConfig.important} ${selector}` - }) + strategy(r) }) rule = container.nodes[0] } } + return [sort | context.layerOrder[layer], rule] }) } diff --git a/tests/layer-at-rules.test.js b/tests/layer-at-rules.test.js index af5218c23f9b..2cab5361e52e 100644 --- a/tests/layer-at-rules.test.js +++ b/tests/layer-at-rules.test.js @@ -50,6 +50,125 @@ test('custom user-land utilities', () => { }) }) +test('comments can be used inside layers without crashing', () => { + let config = { + content: [ + { + raw: html`
`, + }, + ], + corePlugins: { preflight: false }, + theme: {}, + plugins: [], + } + + let input = css` + @tailwind base; + @tailwind components; + @tailwind utilities; + + @layer base { + /* Important base */ + div { + background-color: #bada55; + } + } + + @layer utilities { + /* Important utility */ + .important-utility { + text-align: banana; + } + } + + @layer components { + /* Important component */ + .important-component { + text-align: banana; + } + } + ` + + return run(input, config).then((result) => { + expect(result.css).toMatchFormattedCss(css` + /* Important base */ + div { + background-color: #bada55; + } + + /* Important component */ + .important-component { + text-align: banana; + } + + /* Important utility */ + .important-utility { + text-align: banana; + } + `) + }) +}) + +test('comments can be used inside layers (with important) without crashing', () => { + let config = { + important: true, + content: [ + { + raw: html``, + }, + ], + corePlugins: { preflight: false }, + theme: {}, + plugins: [], + } + + let input = css` + @tailwind base; + @tailwind components; + @tailwind utilities; + + @layer base { + /* Important base */ + div { + background-color: #bada55; + } + } + + @layer utilities { + /* Important utility */ + .important-utility { + text-align: banana; + } + } + + @layer components { + /* Important component */ + .important-component { + text-align: banana; + } + } + ` + + return run(input, config).then((result) => { + expect(result.css).toMatchFormattedCss(css` + /* Important base */ + div { + background-color: #bada55; + } + + /* Important component */ + .important-component { + text-align: banana; + } + + /* Important utility */ + .important-utility { + text-align: banana !important; + } + `) + }) +}) + test('layers are grouped and inserted at the matching @tailwind rule', () => { let config = { content: [