lightningcss/properties/
overflow.rs

1//! CSS properties related to overflow.
2
3use super::{Property, PropertyId};
4use crate::compat::Feature;
5use crate::context::PropertyHandlerContext;
6use crate::declaration::{DeclarationBlock, DeclarationList};
7use crate::error::{ParserError, PrinterError};
8use crate::macros::{define_shorthand, enum_property};
9use crate::printer::Printer;
10use crate::traits::{Parse, PropertyHandler, Shorthand, ToCss};
11#[cfg(feature = "visitor")]
12use crate::visitor::Visit;
13use cssparser::*;
14
15enum_property! {
16  /// An [overflow](https://www.w3.org/TR/css-overflow-3/#overflow-properties) keyword
17  /// as used in the `overflow-x`, `overflow-y`, and `overflow` properties.
18  pub enum OverflowKeyword {
19    /// Overflowing content is visible.
20    Visible,
21    /// Overflowing content is hidden. Programmatic scrolling is allowed.
22    Hidden,
23    /// Overflowing content is clipped. Programmatic scrolling is not allowed.
24    Clip,
25    /// The element is scrollable.
26    Scroll,
27    /// Overflowing content scrolls if needed.
28    Auto,
29  }
30}
31
32define_shorthand! {
33  /// A value for the [overflow](https://www.w3.org/TR/css-overflow-3/#overflow-properties) shorthand property.
34  pub struct Overflow {
35    /// The overflow mode for the x direction.
36    x: OverflowX(OverflowKeyword),
37    /// The overflow mode for the y direction.
38    y: OverflowY(OverflowKeyword),
39  }
40}
41
42impl<'i> Parse<'i> for Overflow {
43  fn parse<'t>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i, ParserError<'i>>> {
44    let x = OverflowKeyword::parse(input)?;
45    let y = input.try_parse(OverflowKeyword::parse).unwrap_or_else(|_| x.clone());
46    Ok(Overflow { x, y })
47  }
48}
49
50impl ToCss for Overflow {
51  fn to_css<W>(&self, dest: &mut Printer<W>) -> Result<(), PrinterError>
52  where
53    W: std::fmt::Write,
54  {
55    self.x.to_css(dest)?;
56    if self.y != self.x {
57      dest.write_char(' ')?;
58      self.y.to_css(dest)?;
59    }
60    Ok(())
61  }
62}
63
64enum_property! {
65  /// A value for the [text-overflow](https://www.w3.org/TR/css-overflow-3/#text-overflow) property.
66  pub enum TextOverflow {
67    /// Overflowing text is clipped.
68    Clip,
69    /// Overflowing text is truncated with an ellipsis.
70    Ellipsis,
71  }
72}
73
74#[derive(Default)]
75pub(crate) struct OverflowHandler {
76  x: Option<OverflowKeyword>,
77  y: Option<OverflowKeyword>,
78}
79
80impl<'i> PropertyHandler<'i> for OverflowHandler {
81  fn handle_property(
82    &mut self,
83    property: &Property<'i>,
84    dest: &mut DeclarationList<'i>,
85    context: &mut PropertyHandlerContext<'i, '_>,
86  ) -> bool {
87    use Property::*;
88
89    match property {
90      OverflowX(val) => self.x = Some(*val),
91      OverflowY(val) => self.y = Some(*val),
92      Overflow(val) => {
93        self.x = Some(val.x);
94        self.y = Some(val.y);
95      }
96      Unparsed(val)
97        if matches!(
98          val.property_id,
99          PropertyId::OverflowX | PropertyId::OverflowY | PropertyId::Overflow
100        ) =>
101      {
102        self.finalize(dest, context);
103        dest.push(property.clone());
104      }
105      _ => return false,
106    }
107
108    true
109  }
110
111  fn finalize(&mut self, dest: &mut DeclarationList, context: &mut PropertyHandlerContext<'i, '_>) {
112    if self.x.is_none() && self.y.is_none() {
113      return;
114    }
115
116    let x = std::mem::take(&mut self.x);
117    let y = std::mem::take(&mut self.y);
118
119    match (x, y) {
120      // Only use shorthand syntax if the x and y values are the
121      // same or the two-value syntax is supported by all targets.
122      (Some(x), Some(y)) if x == y || context.targets.is_compatible(Feature::OverflowShorthand) => {
123        dest.push(Property::Overflow(Overflow { x, y }))
124      }
125      _ => {
126        if let Some(x) = x {
127          dest.push(Property::OverflowX(x))
128        }
129
130        if let Some(y) = y {
131          dest.push(Property::OverflowY(y))
132        }
133      }
134    }
135  }
136}