Skip to content

Commit ee3f3fd

Browse files
authored
Ensure comments in @layer rules don't crash (#5854)
* ensure comments in @layer rules don't crash * update changelog
1 parent 0ab39c3 commit ee3f3fd

File tree

3 files changed

+141
-7
lines changed

3 files changed

+141
-7
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3131
- Fix before/after utilities overriding custom content values at larger breakpoints ([#5820](https://github.com/tailwindlabs/tailwindcss/pull/5820))
3232
- Cleanup duplicate properties ([#5830](https://github.com/tailwindlabs/tailwindcss/pull/5830))
3333
- Allow `_` inside `url()` when using arbitrary values ([#5853](https://github.com/tailwindlabs/tailwindcss/pull/5853))
34+
- Prevent crashes when using comments in `@layer` AtRules ([#5854](https://github.com/tailwindlabs/tailwindcss/pull/5854))
3435

3536
## [3.0.0-alpha.1] - 2021-10-01
3637

src/lib/generateRules.js

+21-7
Original file line numberDiff line numberDiff line change
@@ -448,28 +448,42 @@ function generateRules(candidates, context) {
448448
allRules.push(matches)
449449
}
450450

451-
return allRules.flat(1).map(([{ sort, layer, options }, rule]) => {
452-
if (options.respectImportant) {
453-
if (context.tailwindConfig.important === true) {
451+
// Strategy based on `tailwindConfig.important`
452+
let strategy = ((important) => {
453+
if (important === true) {
454+
return (rule) => {
454455
rule.walkDecls((d) => {
455456
if (d.parent.type === 'rule' && !inKeyframes(d.parent)) {
456457
d.important = true
457458
}
458459
})
459-
} else if (typeof context.tailwindConfig.important === 'string') {
460+
}
461+
}
462+
463+
if (typeof important === 'string') {
464+
return (rule) => {
465+
rule.selectors = rule.selectors.map((selector) => {
466+
return `${important} ${selector}`
467+
})
468+
}
469+
}
470+
})(context.tailwindConfig.important)
471+
472+
return allRules.flat(1).map(([{ sort, layer, options }, rule]) => {
473+
if (options.respectImportant) {
474+
if (strategy) {
460475
let container = postcss.root({ nodes: [rule.clone()] })
461476
container.walkRules((r) => {
462477
if (inKeyframes(r)) {
463478
return
464479
}
465480

466-
r.selectors = r.selectors.map((selector) => {
467-
return `${context.tailwindConfig.important} ${selector}`
468-
})
481+
strategy(r)
469482
})
470483
rule = container.nodes[0]
471484
}
472485
}
486+
473487
return [sort | context.layerOrder[layer], rule]
474488
})
475489
}

tests/layer-at-rules.test.js

+119
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,125 @@ test('custom user-land utilities', () => {
5050
})
5151
})
5252

53+
test('comments can be used inside layers without crashing', () => {
54+
let config = {
55+
content: [
56+
{
57+
raw: html`<div class="important-utility important-component"></div>`,
58+
},
59+
],
60+
corePlugins: { preflight: false },
61+
theme: {},
62+
plugins: [],
63+
}
64+
65+
let input = css`
66+
@tailwind base;
67+
@tailwind components;
68+
@tailwind utilities;
69+
70+
@layer base {
71+
/* Important base */
72+
div {
73+
background-color: #bada55;
74+
}
75+
}
76+
77+
@layer utilities {
78+
/* Important utility */
79+
.important-utility {
80+
text-align: banana;
81+
}
82+
}
83+
84+
@layer components {
85+
/* Important component */
86+
.important-component {
87+
text-align: banana;
88+
}
89+
}
90+
`
91+
92+
return run(input, config).then((result) => {
93+
expect(result.css).toMatchFormattedCss(css`
94+
/* Important base */
95+
div {
96+
background-color: #bada55;
97+
}
98+
99+
/* Important component */
100+
.important-component {
101+
text-align: banana;
102+
}
103+
104+
/* Important utility */
105+
.important-utility {
106+
text-align: banana;
107+
}
108+
`)
109+
})
110+
})
111+
112+
test('comments can be used inside layers (with important) without crashing', () => {
113+
let config = {
114+
important: true,
115+
content: [
116+
{
117+
raw: html`<div class="important-utility important-component"></div>`,
118+
},
119+
],
120+
corePlugins: { preflight: false },
121+
theme: {},
122+
plugins: [],
123+
}
124+
125+
let input = css`
126+
@tailwind base;
127+
@tailwind components;
128+
@tailwind utilities;
129+
130+
@layer base {
131+
/* Important base */
132+
div {
133+
background-color: #bada55;
134+
}
135+
}
136+
137+
@layer utilities {
138+
/* Important utility */
139+
.important-utility {
140+
text-align: banana;
141+
}
142+
}
143+
144+
@layer components {
145+
/* Important component */
146+
.important-component {
147+
text-align: banana;
148+
}
149+
}
150+
`
151+
152+
return run(input, config).then((result) => {
153+
expect(result.css).toMatchFormattedCss(css`
154+
/* Important base */
155+
div {
156+
background-color: #bada55;
157+
}
158+
159+
/* Important component */
160+
.important-component {
161+
text-align: banana;
162+
}
163+
164+
/* Important utility */
165+
.important-utility {
166+
text-align: banana !important;
167+
}
168+
`)
169+
})
170+
})
171+
53172
test('layers are grouped and inserted at the matching @tailwind rule', () => {
54173
let config = {
55174
content: [

0 commit comments

Comments
 (0)