Skip to main content

style/values/specified/
intersection_observer.rs

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