Skip to content

Commit 9f937df

Browse files
committed
Handle position property
1 parent 228f464 commit 9f937df

File tree

5 files changed

+181
-12
lines changed

5 files changed

+181
-12
lines changed

README.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,34 +24,34 @@ A WIP CSS parser, transformer, and minifier written in Rust.
2424

2525
```
2626
$ node bench.js bootstrap-4.css
27-
cssnano: 557.216ms
27+
cssnano: 539.997ms
2828
159636 bytes
2929
30-
esbuild: 17.79ms
30+
esbuild: 17.399ms
3131
160332 bytes
3232
33-
parcel-css: 5.231ms
34-
144293 bytes
33+
parcel-css: 4.975ms
34+
144254 bytes
3535
3636
3737
$ node bench.js animate.css
38-
cssnano: 279.961ms
38+
cssnano: 283.105ms
3939
71723 bytes
4040
41-
esbuild: 11.781ms
41+
esbuild: 11.858ms
4242
72183 bytes
4343
44-
parcel-css: 2.029ms
44+
parcel-css: 2.039ms
4545
23707 bytes
4646
4747
4848
$ node bench.js tailwind.css
49-
cssnano: 2.193s
49+
cssnano: 2.200s
5050
1925626 bytes
5151
52-
esbuild: 106.392ms
52+
esbuild: 109.223ms
5353
1961642 bytes
5454
55-
parcel-css: 43.564ms
56-
1906588 bytes
55+
parcel-css: 41.589ms
56+
1906468 bytes
5757
```

src/declaration.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ use crate::properties::{
1515
prefix_handler::PrefixHandler,
1616
display::DisplayHandler,
1717
transform::TransformHandler,
18-
text::TextDecorationHandler
18+
text::TextDecorationHandler,
19+
position::PositionHandler,
1920
};
2021
use crate::properties::prefixes::Browsers;
2122

@@ -82,6 +83,7 @@ pub struct DeclarationHandler {
8283
transition: TransitionHandler,
8384
animation: AnimationHandler,
8485
display: DisplayHandler,
86+
position: PositionHandler,
8587
transform: TransformHandler,
8688
prefix: PrefixHandler,
8789
decls: DeclarationList
@@ -97,6 +99,7 @@ impl DeclarationHandler{
9799
transition: TransitionHandler::new(targets),
98100
animation: AnimationHandler::new(targets),
99101
display: DisplayHandler::new(targets),
102+
position: PositionHandler::new(targets),
100103
transform: TransformHandler::new(targets),
101104
text: TextDecorationHandler::new(targets),
102105
prefix: PrefixHandler::new(targets),
@@ -121,6 +124,7 @@ impl DeclarationHandler{
121124
self.transition.handle_property(property, &mut self.decls) ||
122125
self.animation.handle_property(property, &mut self.decls) ||
123126
self.display.handle_property(property, &mut self.decls) ||
127+
self.position.handle_property(property, &mut self.decls) ||
124128
self.transform.handle_property(property, &mut self.decls) ||
125129
self.prefix.handle_property(property, &mut self.decls)
126130
}
@@ -140,6 +144,7 @@ impl DeclarationHandler{
140144
self.transition.finalize(&mut self.decls);
141145
self.animation.finalize(&mut self.decls);
142146
self.display.finalize(&mut self.decls);
147+
self.position.finalize(&mut self.decls);
143148
self.transform.finalize(&mut self.decls);
144149
self.prefix.finalize(&mut self.decls);
145150
std::mem::take(&mut self.decls.declarations)

src/lib.rs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4485,4 +4485,60 @@ mod tests {
44854485
minify_test(".foo { text-shadow: 1px 1px yellow; }", ".foo{text-shadow:1px 1px #ff0}");
44864486
minify_test(".foo { text-shadow: 1px 1px yellow, 2px 3px red; }", ".foo{text-shadow:1px 1px #ff0,2px 3px red}");
44874487
}
4488+
4489+
#[test]
4490+
fn test_position() {
4491+
test(r#"
4492+
.foo {
4493+
position: relative;
4494+
position: absolute;
4495+
}
4496+
"#, indoc! {r#"
4497+
.foo {
4498+
position: absolute;
4499+
}
4500+
"#});
4501+
4502+
test(r#"
4503+
.foo {
4504+
position: -webkit-sticky;
4505+
position: sticky;
4506+
}
4507+
"#, indoc! {r#"
4508+
.foo {
4509+
position: -webkit-sticky;
4510+
position: sticky;
4511+
}
4512+
"#});
4513+
4514+
prefix_test(r#"
4515+
.foo {
4516+
position: sticky;
4517+
}
4518+
"#, indoc! {r#"
4519+
.foo {
4520+
position: -webkit-sticky;
4521+
position: sticky;
4522+
}
4523+
"#},
4524+
Browsers {
4525+
safari: Some(8 << 16),
4526+
..Browsers::default()
4527+
});
4528+
4529+
prefix_test(r#"
4530+
.foo {
4531+
position: -webkit-sticky;
4532+
position: sticky;
4533+
}
4534+
"#, indoc! {r#"
4535+
.foo {
4536+
position: sticky;
4537+
}
4538+
"#},
4539+
Browsers {
4540+
safari: Some(13 << 16),
4541+
..Browsers::default()
4542+
});
4543+
}
44884544
}

src/properties/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ pub mod prefixes;
1616
pub mod prefix_handler;
1717
pub mod display;
1818
pub mod text;
19+
pub mod position;
1920

2021
use cssparser::*;
2122
use custom::*;
@@ -222,6 +223,8 @@ define_properties! {
222223
"max-inline-size": MaxInlineSize(MinMaxSize),
223224
"box-sizing": BoxSizing(BoxSizing, VendorPrefix) / "webkit" / "moz",
224225

226+
// https://www.w3.org/TR/2020/WD-css-position-3-20200519
227+
"position": Position(position::Position),
225228
"top": Top(LengthPercentageOrAuto),
226229
"bottom": Bottom(LengthPercentageOrAuto),
227230
"left": Left(LengthPercentageOrAuto),

src/properties/position.rs

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
use cssparser::*;
2+
use crate::traits::{Parse, ToCss, PropertyHandler};
3+
use super::{Property, VendorPrefix};
4+
use super::prefixes::{Feature, Browsers};
5+
use crate::declaration::DeclarationList;
6+
use crate::printer::Printer;
7+
8+
/// https://www.w3.org/TR/2020/WD-css-position-3-20200519/#position-property
9+
#[derive(Debug, Clone, PartialEq)]
10+
pub enum Position {
11+
Static,
12+
Relative,
13+
Absolute,
14+
Sticky(VendorPrefix),
15+
Fixed
16+
}
17+
18+
impl Parse for Position {
19+
fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i, ()>> {
20+
let location = input.current_source_location();
21+
let ident = input.expect_ident()?;
22+
match_ignore_ascii_case! { &*ident,
23+
"static" => Ok(Position::Static),
24+
"relative" => Ok(Position::Relative),
25+
"absolute" => Ok(Position::Absolute),
26+
"fixed" => Ok(Position::Fixed),
27+
"sticky" => Ok(Position::Sticky(VendorPrefix::None)),
28+
"-webkit-sticky" => Ok(Position::Sticky(VendorPrefix::WebKit)),
29+
_ => Err(location.new_unexpected_token_error(
30+
cssparser::Token::Ident(ident.clone())
31+
))
32+
}
33+
}
34+
}
35+
36+
impl ToCss for Position {
37+
fn to_css<W>(&self, dest: &mut Printer<W>) -> std::fmt::Result where W: std::fmt::Write {
38+
match self {
39+
Position::Static => dest.write_str("static"),
40+
Position::Relative => dest.write_str("relative"),
41+
Position::Absolute => dest.write_str("absolute"),
42+
Position::Fixed => dest.write_str("fixed"),
43+
Position::Sticky(prefix) => {
44+
prefix.to_css(dest)?;
45+
dest.write_str("sticky")
46+
}
47+
}
48+
}
49+
}
50+
51+
#[derive(Default)]
52+
pub struct PositionHandler {
53+
targets: Option<Browsers>,
54+
position: Option<Position>
55+
}
56+
57+
impl PositionHandler {
58+
pub fn new(targets: Option<Browsers>) -> PositionHandler {
59+
PositionHandler {
60+
targets,
61+
..PositionHandler::default()
62+
}
63+
}
64+
}
65+
66+
impl PropertyHandler for PositionHandler {
67+
fn handle_property(&mut self, property: &Property, _: &mut DeclarationList) -> bool {
68+
if let Property::Position(position) = property {
69+
if let (Some(Position::Sticky(cur)), Position::Sticky(new)) = (&mut self.position, position) {
70+
*cur |= *new;
71+
} else {
72+
self.position = Some(position.clone());
73+
}
74+
75+
return true
76+
}
77+
78+
false
79+
}
80+
81+
fn finalize(&mut self, dest: &mut DeclarationList) {
82+
if let Some(position) = std::mem::take(&mut self.position) {
83+
match position {
84+
Position::Sticky(mut prefix) => {
85+
if prefix.contains(VendorPrefix::None) {
86+
if let Some(targets) = self.targets {
87+
prefix = Feature::Sticky.prefixes_for(targets)
88+
}
89+
}
90+
91+
if prefix.contains(VendorPrefix::WebKit) {
92+
dest.push(Property::Position(Position::Sticky(VendorPrefix::WebKit)))
93+
}
94+
95+
if prefix.contains(VendorPrefix::None) {
96+
dest.push(Property::Position(Position::Sticky(VendorPrefix::None)))
97+
}
98+
}
99+
_ => {
100+
dest.push(Property::Position(position))
101+
}
102+
}
103+
}
104+
}
105+
}

0 commit comments

Comments
 (0)