lightningcss/properties/
overflow.rs1use 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 pub enum OverflowKeyword {
19 Visible,
21 Hidden,
23 Clip,
25 Scroll,
27 Auto,
29 }
30}
31
32define_shorthand! {
33 pub struct Overflow {
35 x: OverflowX(OverflowKeyword),
37 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 pub enum TextOverflow {
67 Clip,
69 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 (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}