lightningcss/properties/
position.rs1use super::Property;
4use crate::context::PropertyHandlerContext;
5use crate::declaration::DeclarationList;
6use crate::error::{ParserError, PrinterError};
7use crate::prefixes::Feature;
8use crate::printer::Printer;
9use crate::traits::{Parse, PropertyHandler, ToCss};
10use crate::values::number::CSSInteger;
11use crate::vendor_prefix::VendorPrefix;
12#[cfg(feature = "visitor")]
13use crate::visitor::Visit;
14use cssparser::*;
15
16#[derive(Debug, Clone, PartialEq)]
18#[cfg_attr(feature = "visitor", derive(Visit))]
19#[cfg_attr(
20 feature = "serde",
21 derive(serde::Serialize, serde::Deserialize),
22 serde(tag = "type", content = "value", rename_all = "kebab-case")
23)]
24#[cfg_attr(feature = "jsonschema", derive(schemars::JsonSchema))]
25#[cfg_attr(feature = "into_owned", derive(static_self::IntoOwned))]
26pub enum Position {
27 Static,
29 Relative,
31 Absolute,
33 Sticky(VendorPrefix),
35 Fixed,
37}
38
39impl<'i> Parse<'i> for Position {
40 fn parse<'t>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i, ParserError<'i>>> {
41 let location = input.current_source_location();
42 let ident = input.expect_ident()?;
43 match_ignore_ascii_case! { &*ident,
44 "static" => Ok(Position::Static),
45 "relative" => Ok(Position::Relative),
46 "absolute" => Ok(Position::Absolute),
47 "fixed" => Ok(Position::Fixed),
48 "sticky" => Ok(Position::Sticky(VendorPrefix::None)),
49 "-webkit-sticky" => Ok(Position::Sticky(VendorPrefix::WebKit)),
50 _ => Err(location.new_unexpected_token_error(
51 cssparser::Token::Ident(ident.clone())
52 ))
53 }
54 }
55}
56
57impl ToCss for Position {
58 fn to_css<W>(&self, dest: &mut Printer<W>) -> Result<(), PrinterError>
59 where
60 W: std::fmt::Write,
61 {
62 match self {
63 Position::Static => dest.write_str("static"),
64 Position::Relative => dest.write_str("relative"),
65 Position::Absolute => dest.write_str("absolute"),
66 Position::Fixed => dest.write_str("fixed"),
67 Position::Sticky(prefix) => {
68 prefix.to_css(dest)?;
69 dest.write_str("sticky")
70 }
71 }
72 }
73}
74
75#[derive(Debug, Clone, PartialEq, Parse, ToCss)]
77#[cfg_attr(feature = "visitor", derive(Visit))]
78#[cfg_attr(
79 feature = "serde",
80 derive(serde::Serialize, serde::Deserialize),
81 serde(tag = "type", content = "value", rename_all = "kebab-case")
82)]
83#[cfg_attr(feature = "jsonschema", derive(schemars::JsonSchema))]
84#[cfg_attr(feature = "into_owned", derive(static_self::IntoOwned))]
85pub enum ZIndex {
86 Auto,
88 Integer(CSSInteger),
90}
91
92#[derive(Default)]
93pub(crate) struct PositionHandler {
94 position: Option<Position>,
95}
96
97impl<'i> PropertyHandler<'i> for PositionHandler {
98 fn handle_property(
99 &mut self,
100 property: &Property<'i>,
101 _: &mut DeclarationList<'i>,
102 _: &mut PropertyHandlerContext<'i, '_>,
103 ) -> bool {
104 if let Property::Position(position) = property {
105 if let (Some(Position::Sticky(cur)), Position::Sticky(new)) = (&mut self.position, position) {
106 *cur |= *new;
107 } else {
108 self.position = Some(position.clone());
109 }
110
111 return true;
112 }
113
114 false
115 }
116
117 fn finalize(&mut self, dest: &mut DeclarationList, context: &mut PropertyHandlerContext<'i, '_>) {
118 if self.position.is_none() {
119 return;
120 }
121
122 if let Some(position) = std::mem::take(&mut self.position) {
123 match position {
124 Position::Sticky(mut prefix) => {
125 prefix = context.targets.prefixes(prefix, Feature::Sticky);
126 if prefix.contains(VendorPrefix::WebKit) {
127 dest.push(Property::Position(Position::Sticky(VendorPrefix::WebKit)))
128 }
129
130 if prefix.contains(VendorPrefix::None) {
131 dest.push(Property::Position(Position::Sticky(VendorPrefix::None)))
132 }
133 }
134 _ => dest.push(Property::Position(position)),
135 }
136 }
137 }
138}