swc_css_minifier/compressor/
supports.rs1use std::mem::take;
2
3use swc_common::DUMMY_SP;
4use swc_css_ast::*;
5
6use super::Compressor;
7use crate::util::dedup;
8
9impl Compressor {
10 fn is_first_supports_in_parens(&self, supports_condition: &SupportsCondition) -> bool {
11 if let Some(SupportsConditionType::SupportsInParens(_)) =
12 supports_condition.conditions.first()
13 {
14 true
15 } else {
16 false
17 }
18 }
19
20 fn is_first_or_supports_type(&self, supports_condition: &SupportsCondition) -> bool {
21 matches!(
22 supports_condition.conditions.get(1),
23 Some(SupportsConditionType::Or(_))
24 )
25 }
26
27 fn is_first_and_supports_type(&self, supports_condition: &SupportsCondition) -> bool {
28 matches!(
29 supports_condition.conditions.get(1),
30 Some(SupportsConditionType::And(_))
31 )
32 }
33
34 pub(super) fn compress_supports_condition(&mut self, n: &mut SupportsCondition) {
35 match n.conditions.get(1) {
36 Some(SupportsConditionType::Or(_)) => {
37 let need_compress = n.conditions.iter().any(|item| match item {
38 SupportsConditionType::SupportsInParens(
39 SupportsInParens::SupportsCondition(supports_condition),
40 ) if self.is_first_or_supports_type(supports_condition)
41 && self.is_first_supports_in_parens(supports_condition) =>
42 {
43 true
44 }
45 SupportsConditionType::Or(supports_or) => match &*supports_or.condition {
46 SupportsInParens::SupportsCondition(supports_condition)
47 if self.is_first_or_supports_type(supports_condition)
48 && self.is_first_supports_in_parens(supports_condition) =>
49 {
50 true
51 }
52 _ => false,
53 },
54 _ => false,
55 });
56
57 if need_compress {
58 let mut new_conditions = Vec::with_capacity(n.conditions.len());
59
60 for item in take(&mut n.conditions) {
61 match item {
62 SupportsConditionType::SupportsInParens(
63 SupportsInParens::SupportsCondition(supports_condition),
64 ) if self.is_first_or_supports_type(&supports_condition)
65 && self.is_first_supports_in_parens(&supports_condition) =>
66 {
67 let mut iter = supports_condition.conditions.into_iter();
68
69 if let Some(SupportsConditionType::SupportsInParens(
70 supports_in_parens,
71 )) = iter.next()
72 {
73 new_conditions.push(SupportsConditionType::SupportsInParens(
74 supports_in_parens,
75 ));
76
77 new_conditions.extend(iter);
78 }
79 }
80 SupportsConditionType::Or(supports_or) => {
81 match *supports_or.condition {
82 SupportsInParens::SupportsCondition(supports_condition)
83 if self.is_first_or_supports_type(&supports_condition)
84 && self.is_first_supports_in_parens(
85 &supports_condition,
86 ) =>
87 {
88 let mut iter = supports_condition.conditions.into_iter();
89
90 if let Some(SupportsConditionType::SupportsInParens(
91 supports_in_parens,
92 )) = iter.next()
93 {
94 new_conditions.push(SupportsConditionType::Or(
95 SupportsOr {
96 span: DUMMY_SP,
97 keyword: None,
98 condition: Box::new(supports_in_parens),
99 },
100 ));
101
102 new_conditions.extend(iter);
103 }
104 }
105 _ => {
106 new_conditions.push(SupportsConditionType::Or(supports_or));
107 }
108 }
109 }
110 _ => {
111 new_conditions.push(item);
112 }
113 }
114 }
115
116 n.conditions = new_conditions;
117 }
118 }
119 Some(SupportsConditionType::And(_)) => {
120 let need_compress = n.conditions.iter().any(|item| match item {
121 SupportsConditionType::SupportsInParens(
122 SupportsInParens::SupportsCondition(supports_condition),
123 ) if self.is_first_and_supports_type(supports_condition)
124 && self.is_first_supports_in_parens(supports_condition) =>
125 {
126 true
127 }
128 SupportsConditionType::And(supports_and) => match &*supports_and.condition {
129 SupportsInParens::SupportsCondition(supports_condition)
130 if self.is_first_and_supports_type(supports_condition)
131 && self.is_first_supports_in_parens(supports_condition) =>
132 {
133 true
134 }
135 _ => false,
136 },
137 _ => false,
138 });
139
140 if need_compress {
141 let mut new_conditions = Vec::with_capacity(n.conditions.len());
142
143 for item in take(&mut n.conditions) {
144 match item {
145 SupportsConditionType::SupportsInParens(
146 SupportsInParens::SupportsCondition(supports_condition),
147 ) if self.is_first_and_supports_type(&supports_condition)
148 && self.is_first_supports_in_parens(&supports_condition) =>
149 {
150 let mut iter = supports_condition.conditions.into_iter();
151
152 if let Some(SupportsConditionType::SupportsInParens(
153 supports_in_parens,
154 )) = iter.next()
155 {
156 new_conditions.push(SupportsConditionType::SupportsInParens(
157 supports_in_parens,
158 ));
159
160 new_conditions.extend(iter);
161 }
162 }
163 SupportsConditionType::And(supports_and) => match *supports_and
164 .condition
165 {
166 SupportsInParens::SupportsCondition(supports_condition)
167 if self.is_first_and_supports_type(&supports_condition)
168 && self
169 .is_first_supports_in_parens(&supports_condition) =>
170 {
171 let mut iter = supports_condition.conditions.into_iter();
172
173 if let Some(SupportsConditionType::SupportsInParens(
174 supports_in_parens,
175 )) = iter.next()
176 {
177 new_conditions.push(SupportsConditionType::And(
178 SupportsAnd {
179 span: DUMMY_SP,
180 keyword: None,
181 condition: Box::new(supports_in_parens),
182 },
183 ));
184
185 new_conditions.extend(iter);
186 }
187 }
188 _ => {
189 new_conditions.push(SupportsConditionType::And(supports_and));
190 }
191 },
192 _ => {
193 new_conditions.push(item);
194 }
195 }
196 }
197
198 n.conditions = new_conditions;
199 }
200 }
201 _ => {}
202 }
203
204 dedup(&mut n.conditions);
205 }
206
207 pub(super) fn compress_supports_in_parens(&mut self, n: &mut SupportsInParens) {
208 match n {
209 SupportsInParens::SupportsCondition(supports_condition)
210 if supports_condition.conditions.len() == 1 =>
211 {
212 if let Some(SupportsConditionType::SupportsInParens(supports_in_parens)) =
213 supports_condition.conditions.first()
214 {
215 *n = supports_in_parens.clone();
216 }
217 }
218 _ => {}
219 }
220 }
221}