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