Skip to content

Commit a1ccfd5

Browse files
committed
Border shorthand minifier
1 parent f2c16f5 commit a1ccfd5

File tree

9 files changed

+742
-25
lines changed

9 files changed

+742
-25
lines changed

Cargo.lock

Lines changed: 16 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ serde_bytes = "0.11.5"
1515
cssparser = "0.28.1"
1616
cssparser-macros = "*"
1717
selectors = "*"
18+
indoc = "*"
1819

1920
[build-dependencies]
2021
napi-build = { version = "1" }

src/lib.rs

Lines changed: 217 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,18 @@ fn transform(ctx: CallContext) -> napi::Result<JsUndefined> {
3030
let config: Config = ctx.env.from_js_value(opts)?;
3131

3232
let code = unsafe { std::str::from_utf8_unchecked(&config.code) };
33+
34+
// for (pos, declarations) in rule_list.flatten() {
35+
// println!("{:?}", declarations);
36+
// }
37+
38+
let res = compile(code);
39+
println!("{}", res);
40+
41+
ctx.env.get_undefined()
42+
}
43+
44+
fn compile(code: &str) -> String {
3345
let mut input = ParserInput::new(&code);
3446
let mut parser = Parser::new(&mut input);
3547
let rule_list = RuleListParser::new_for_stylesheet(&mut parser, TopLevelRuleParser {});
@@ -47,7 +59,7 @@ fn transform(ctx: CallContext) -> napi::Result<JsUndefined> {
4759
url: "test".into()
4860
})
4961
},
50-
parser::CssRule::Style(style) => {
62+
parser::CssRule::Style(mut style) => {
5163
for selector in style.selectors.0.iter() {
5264
for x in selector.iter() {
5365
match x {
@@ -66,15 +78,16 @@ fn transform(ctx: CallContext) -> napi::Result<JsUndefined> {
6678
}
6779
}
6880

81+
style.minify();
82+
6983
parser::CssRule::Style(style)
7084
},
7185
r => r
7286
};
7387
rule.to_css_string()
7488
}).collect::<Vec<String>>().join("\n\n");
75-
println!("{}", res);
7689

77-
ctx.env.get_undefined()
90+
res
7891
}
7992

8093
#[module_exports]
@@ -83,3 +96,204 @@ fn init(mut exports: JsObject) -> napi::Result<()> {
8396

8497
Ok(())
8598
}
99+
100+
#[cfg(test)]
101+
mod tests {
102+
use super::*;
103+
extern crate indoc;
104+
use self::indoc::indoc;
105+
106+
fn test(source: &str, expected: &str) {
107+
let res = compile(source);
108+
assert_eq!(res, expected);
109+
}
110+
111+
#[test]
112+
pub fn test_border() {
113+
test(r#"
114+
.foo {
115+
border-left: 2px solid red;
116+
border-right: 2px solid red;
117+
border-bottom: 2px solid red;
118+
border-top: 2px solid red;
119+
}
120+
"#, indoc! {r#"
121+
.foo {
122+
border: 2.0px solid #f00;
123+
}"#
124+
});
125+
126+
test(r#"
127+
.foo {
128+
border-left-color: red;
129+
border-right-color: red;
130+
border-bottom-color: red;
131+
border-top-color: red;
132+
}
133+
"#, indoc! {r#"
134+
.foo {
135+
border-color: #f00;
136+
}"#
137+
});
138+
139+
test(r#"
140+
.foo {
141+
border-left-width: thin;
142+
border-right-width: thin;
143+
border-bottom-width: thin;
144+
border-top-width: thin;
145+
}
146+
"#, indoc! {r#"
147+
.foo {
148+
border-width: thin;
149+
}"#
150+
});
151+
152+
test(r#"
153+
.foo {
154+
border-left-style: dotted;
155+
border-right-style: dotted;
156+
border-bottom-style: dotted;
157+
border-top-style: dotted;
158+
}
159+
"#, indoc! {r#"
160+
.foo {
161+
border-style: dotted;
162+
}"#
163+
});
164+
165+
test(r#"
166+
.foo {
167+
border-left-width: thin;
168+
border-left-style: dotted;
169+
border-left-color: red;
170+
}
171+
"#, indoc! {r#"
172+
.foo {
173+
border-left: thin dotted #f00;
174+
}"#
175+
});
176+
177+
test(r#"
178+
.foo {
179+
border-left-width: thick;
180+
border-left: thin dotted red;
181+
}
182+
"#, indoc! {r#"
183+
.foo {
184+
border-left: thin dotted #f00;
185+
}"#
186+
});
187+
188+
test(r#"
189+
.foo {
190+
border-left-width: thick;
191+
border: thin dotted red;
192+
}
193+
"#, indoc! {r#"
194+
.foo {
195+
border: thin dotted #f00;
196+
}"#
197+
});
198+
199+
test(r#"
200+
.foo {
201+
border: thin dotted red;
202+
border-right-width: thick;
203+
}
204+
"#, indoc! {r#"
205+
.foo {
206+
border: thin dotted #f00;
207+
border-right-width: thick;
208+
}"#
209+
});
210+
211+
test(r#"
212+
.foo {
213+
border: thin dotted red;
214+
border-right: thick dotted red;
215+
}
216+
"#, indoc! {r#"
217+
.foo {
218+
border: thin dotted #f00;
219+
border-right-width: thick;
220+
}"#
221+
});
222+
223+
test(r#"
224+
.foo {
225+
border: thin dotted red;
226+
border-right-width: thick;
227+
border-right-style: solid;
228+
}
229+
"#, indoc! {r#"
230+
.foo {
231+
border: thin dotted #f00;
232+
border-right: thick solid #f00;
233+
}"#
234+
});
235+
236+
test(r#"
237+
.foo {
238+
border-top: thin dotted red;
239+
border-block-start: thick solid green;
240+
}
241+
"#, indoc! {r#"
242+
.foo {
243+
border-top: thin dotted #f00;
244+
border-block-start: thick solid #008000;
245+
}"#
246+
});
247+
248+
test(r#"
249+
.foo {
250+
border: thin dotted red;
251+
border-block-start-width: thick;
252+
border-left-width: medium;
253+
}
254+
"#, indoc! {r#"
255+
.foo {
256+
border: thin dotted #f00;
257+
border-block-start-width: thick;
258+
border-left-width: medium;
259+
}"#
260+
});
261+
262+
test(r#"
263+
.foo {
264+
border-block-start: thin dotted red;
265+
border-inline-end: thin dotted red;
266+
}
267+
"#, indoc! {r#"
268+
.foo {
269+
border-block-start: thin dotted #f00;
270+
border-inline-end: thin dotted #f00;
271+
}"#
272+
});
273+
274+
test(r#"
275+
.foo {
276+
border-block-start-width: thin;
277+
border-block-start-style: dotted;
278+
border-block-start-color: red;
279+
border-inline-end: thin dotted #f00;
280+
}
281+
"#, indoc! {r#"
282+
.foo {
283+
border-block-start: thin dotted #f00;
284+
border-inline-end: thin dotted #f00;
285+
}"#
286+
});
287+
288+
test(r#"
289+
.foo {
290+
border-block-start: thin dotted red;
291+
border-block-end: thin dotted red;
292+
}
293+
"#, indoc! {r#"
294+
.foo {
295+
border-block: thin dotted #f00;
296+
}"#
297+
});
298+
}
299+
}

src/parser.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,7 @@ impl ToCss for StyleRule {
366366
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
367367
// dest.write_str(&self.selectors)?;
368368
self.selectors.to_css(dest)?;
369-
dest.write_str(" { ")?;
369+
dest.write_str(" {")?;
370370
for prop in self.declarations.iter() {
371371
dest.write_str("\n ")?;
372372
prop.to_css(dest)?;
@@ -375,6 +375,24 @@ impl ToCss for StyleRule {
375375
}
376376
}
377377

378+
impl StyleRule {
379+
pub fn minify(&mut self) {
380+
use crate::values::border::*;
381+
382+
let mut border_handler = BorderHandler::default();
383+
384+
let mut decls = vec![];
385+
for decl in self.declarations.iter() {
386+
if !border_handler.handle_property(decl) {
387+
decls.push(decl.clone());
388+
}
389+
}
390+
391+
decls.extend(border_handler.finalize());
392+
self.declarations = decls;
393+
}
394+
}
395+
378396
#[derive(Debug)]
379397
pub enum CssRule {
380398
Media(MediaRule),

src/properties/custom.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use cssparser::*;
22

3-
#[derive(Debug)]
3+
#[derive(Debug, Clone)]
44
pub struct CustomProperty {
55
pub name: String,
66
pub value: String

0 commit comments

Comments
 (0)