intersection_observer.rs (3092B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ 4 5 //! Specified types for intersection observer that utilizes style parser. 6 //! 7 //! <https://w3c.github.io/IntersectionObserver/#intersection-observer-api> 8 9 use crate::parser::{Parse, ParserContext}; 10 use crate::values::computed::{self, Length, LengthPercentage}; 11 use crate::values::generics::rect::Rect; 12 use cssparser::{match_ignore_ascii_case, Parser, Token}; 13 use std::fmt; 14 use style_traits::values::SequenceWriter; 15 use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss}; 16 17 fn parse_pixel_or_percent<'i, 't>( 18 _context: &ParserContext, 19 input: &mut Parser<'i, 't>, 20 ) -> Result<LengthPercentage, ParseError<'i>> { 21 let location = input.current_source_location(); 22 let token = input.next()?; 23 let value = match *token { 24 Token::Dimension { 25 value, ref unit, .. 26 } => { 27 match_ignore_ascii_case! { unit, 28 "px" => Ok(LengthPercentage::new_length(Length::new(value))), 29 _ => Err(()), 30 } 31 }, 32 Token::Percentage { unit_value, .. } => Ok(LengthPercentage::new_percent( 33 computed::Percentage(unit_value), 34 )), 35 _ => Err(()), 36 }; 37 value.map_err(|()| location.new_custom_error(StyleParseErrorKind::UnspecifiedError)) 38 } 39 40 /// The value of an IntersectionObserver's (root or scroll) margin property. 41 /// 42 /// Only bare px or percentage values are allowed. Other length units and 43 /// calc() values are not allowed. 44 /// 45 /// <https://w3c.github.io/IntersectionObserver/#parse-a-margin> 46 #[repr(transparent)] 47 pub struct IntersectionObserverMargin(pub Rect<LengthPercentage>); 48 49 impl Parse for IntersectionObserverMargin { 50 fn parse<'i, 't>( 51 context: &ParserContext, 52 input: &mut Parser<'i, 't>, 53 ) -> Result<Self, ParseError<'i>> { 54 use crate::Zero; 55 if input.is_exhausted() { 56 // If there are zero elements in tokens, set tokens to ["0px"]. 57 return Ok(IntersectionObserverMargin(Rect::all( 58 LengthPercentage::zero(), 59 ))); 60 } 61 let rect = Rect::parse_with(context, input, parse_pixel_or_percent)?; 62 Ok(IntersectionObserverMargin(rect)) 63 } 64 } 65 66 // Strictly speaking this is not ToCss. It's serializing for DOM. But 67 // we can just reuse the infrastructure of this. 68 // 69 // <https://w3c.github.io/IntersectionObserver/#dom-intersectionobserver-rootmargin> 70 impl ToCss for IntersectionObserverMargin { 71 fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result 72 where 73 W: fmt::Write, 74 { 75 // We cannot use the ToCss impl of Rect, because that would 76 // merge items when they are equal. We want to list them all. 77 let mut writer = SequenceWriter::new(dest, " "); 78 let rect = &self.0; 79 writer.item(&rect.0)?; 80 writer.item(&rect.1)?; 81 writer.item(&rect.2)?; 82 writer.item(&rect.3) 83 } 84 }