Skip to content

Commit b31e4ed

Browse files
committed
Expand vendor prefixes from bitflags
1 parent 7367264 commit b31e4ed

File tree

3 files changed

+76
-53
lines changed

3 files changed

+76
-53
lines changed

src/declaration.rs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,7 @@ impl Declaration {
3333

3434
impl ToCss for Declaration {
3535
fn to_css<W>(&self, dest: &mut Printer<W>) -> std::fmt::Result where W: std::fmt::Write {
36-
self.property.to_css(dest)?;
37-
if self.important {
38-
dest.whitespace()?;
39-
dest.write_str("!important")?;
40-
}
41-
Ok(())
36+
self.property.to_css(dest, self.important)
4237
}
4338
}
4439

src/properties/mod.rs

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ use crate::traits::{Parse, ToCss};
3232
use crate::printer::Printer;
3333
use smallvec::{SmallVec, smallvec};
3434
use bitflags::bitflags;
35+
use std::fmt::Write;
3536

3637
bitflags! {
3738
pub struct VendorPrefix: u8 {
@@ -109,24 +110,70 @@ macro_rules! define_properties {
109110
return Ok(Property::Custom(CustomProperty::parse(name, input)?))
110111
}
111112

112-
pub fn to_css<W>(&self, dest: &mut Printer<W>) -> std::fmt::Result where W: std::fmt::Write {
113+
pub fn to_css<W>(&self, dest: &mut Printer<W>, important: bool) -> std::fmt::Result where W: std::fmt::Write {
113114
use Property::*;
114115

115116
match self {
116117
$(
117118
$property(val, $($vp)?) => {
118-
$($vp.to_css(dest)?;)?
119-
dest.write_str($name)?;
120-
dest.delim(':', false)?;
121-
val.to_css(dest)
119+
// If there are multiple vendor prefixes set, this expands them.
120+
let mut first = true;
121+
macro_rules! start {
122+
() => {
123+
if first {
124+
first = false;
125+
} else {
126+
dest.write_char(';')?;
127+
if !dest.minify {
128+
dest.write_str("\n ")?;
129+
}
130+
}
131+
};
132+
}
133+
134+
macro_rules! write {
135+
() => {
136+
dest.write_str($name)?;
137+
dest.delim(':', false)?;
138+
val.to_css(dest)?;
139+
if important {
140+
dest.whitespace()?;
141+
dest.write_str("!important")?;
142+
}
143+
};
144+
($p: expr) => {
145+
start!();
146+
write!();
147+
};
148+
($v: ident, $p: expr) => {
149+
if $v.contains($p) {
150+
start!();
151+
$p.to_css(dest)?;
152+
write!();
153+
}
154+
};
155+
}
156+
157+
$(
158+
write!($vp, VendorPrefix::WebKit);
159+
write!($vp, VendorPrefix::Moz);
160+
write!($vp, VendorPrefix::Ms);
161+
)?
162+
163+
write!($($vp,)? VendorPrefix::None);
122164
}
123165
)+
124166
Custom(custom) => {
125167
dest.write_str(custom.name.as_ref())?;
126168
dest.delim(':', false)?;
127-
dest.write_str(custom.value.as_ref())
169+
dest.write_str(custom.value.as_ref())?;
170+
if important {
171+
dest.whitespace()?;
172+
dest.write_str("!important")?;
173+
}
128174
}
129175
}
176+
Ok(())
130177
}
131178
}
132179
};

src/properties/transition.rs

Lines changed: 22 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -156,26 +156,6 @@ impl TransitionHandler {
156156
let mut delays = std::mem::take(&mut self.delays);
157157
let mut timing_functions = std::mem::take(&mut self.timing_functions);
158158

159-
macro_rules! expand {
160-
($prop: ident, $val: ident, $prefixes: ident) => {
161-
if $prefixes.contains(VendorPrefix::WebKit) {
162-
self.decls.push(Property::$prop($val.clone(), VendorPrefix::WebKit));
163-
}
164-
165-
if $prefixes.contains(VendorPrefix::Moz) {
166-
self.decls.push(Property::$prop($val.clone(), VendorPrefix::Moz));
167-
}
168-
169-
if $prefixes.contains(VendorPrefix::Ms) {
170-
self.decls.push(Property::$prop($val.clone(), VendorPrefix::Ms));
171-
}
172-
173-
if $prefixes.contains(VendorPrefix::None) {
174-
self.decls.push(Property::$prop($val, VendorPrefix::None));
175-
}
176-
};
177-
}
178-
179159
if let (Some((properties, property_prefixes)), Some((durations, duration_prefixes)), Some((delays, delay_prefixes)), Some((timing_functions, timing_prefixes))) = (&mut properties, &mut durations, &mut delays, &mut timing_functions) {
180160
// Only use shorthand syntax if the number of transitions matches on all properties.
181161
let len = properties.len();
@@ -189,41 +169,42 @@ impl TransitionHandler {
189169
}
190170
}).collect();
191171

192-
macro_rules! handle_prefix {
193-
($prefix: ident) => {
194-
// If all properties have this vendor prefix, use the shorthand syntax.
195-
// Otherwise, we'll fall through below to individual properties.
196-
if property_prefixes.contains(VendorPrefix::$prefix) && duration_prefixes.contains(VendorPrefix::$prefix) && delay_prefixes.contains(VendorPrefix::$prefix) && timing_prefixes.contains(VendorPrefix::$prefix) {
197-
self.decls.push(Property::Transition(transitions.clone(), VendorPrefix::$prefix));
198-
property_prefixes.remove(VendorPrefix::$prefix);
199-
duration_prefixes.remove(VendorPrefix::$prefix);
200-
delay_prefixes.remove(VendorPrefix::$prefix);
201-
timing_prefixes.remove(VendorPrefix::$prefix);
202-
}
203-
};
172+
// Find the intersection of prefixes with the same value.
173+
// Remove that from the prefixes of each of the properties. The remaining
174+
// prefixes will be handled by outputing individual properties below.
175+
let intersection = *property_prefixes & *duration_prefixes & *delay_prefixes & *timing_prefixes;
176+
if !intersection.is_empty() {
177+
self.decls.push(Property::Transition(transitions.clone(), intersection));
178+
property_prefixes.remove(intersection);
179+
duration_prefixes.remove(intersection);
180+
delay_prefixes.remove(intersection);
181+
timing_prefixes.remove(intersection);
204182
}
205-
206-
handle_prefix!(WebKit);
207-
handle_prefix!(Moz);
208-
handle_prefix!(Ms);
209-
handle_prefix!(None);
210183
}
211184
}
212185

213186
if let Some((properties, prefix)) = properties {
214-
expand!(TransitionProperty, properties, prefix);
187+
if !prefix.is_empty() {
188+
self.decls.push(Property::TransitionProperty(properties, prefix));
189+
}
215190
}
216191

217192
if let Some((durations, prefix)) = durations {
218-
expand!(TransitionDuration, durations, prefix);
193+
if !prefix.is_empty() {
194+
self.decls.push(Property::TransitionDuration(durations, prefix));
195+
}
219196
}
220197

221198
if let Some((delays, prefix)) = delays {
222-
expand!(TransitionDelay, delays, prefix);
199+
if !prefix.is_empty() {
200+
self.decls.push(Property::TransitionDelay(delays, prefix));
201+
}
223202
}
224203

225204
if let Some((timing_functions, prefix)) = timing_functions {
226-
expand!(TransitionTimingFunction, timing_functions, prefix);
205+
if !prefix.is_empty() {
206+
self.decls.push(Property::TransitionTimingFunction(timing_functions, prefix));
207+
}
227208
}
228209

229210
self.reset();

0 commit comments

Comments
 (0)