Skip to main content

takumi_css/style/properties/
line_clamp.rs

1use cssparser::Parser;
2use std::fmt;
3
4use crate::style::{
5  CssSyntaxKind, CssToken, FromCss, MakeComputed, ParseResult, ToCss, properties::write_css_string,
6  tw::TailwindPropertyParser,
7};
8
9#[derive(Debug, Clone, PartialEq)]
10/// Represents a line clamp value.
11#[non_exhaustive]
12pub struct LineClamp {
13  /// The number of lines to clamp.
14  pub count: u32,
15  /// The ellipsis character to use when the text is clamped.
16  pub ellipsis: Option<String>,
17}
18
19impl MakeComputed for LineClamp {}
20
21impl TailwindPropertyParser for LineClamp {
22  fn parse_tw(token: &str) -> Option<Self> {
23    if token.eq_ignore_ascii_case("none") {
24      return Some(LineClamp {
25        count: 0,
26        ellipsis: None,
27      });
28    }
29    let count = token.parse::<u32>().ok()?;
30    if count == 0 {
31      return None;
32    }
33    Some(LineClamp {
34      count,
35      ellipsis: None,
36    })
37  }
38}
39
40impl From<u32> for LineClamp {
41  fn from(count: u32) -> Self {
42    Self {
43      count,
44      ellipsis: None,
45    }
46  }
47}
48
49impl<'i> FromCss<'i> for LineClamp {
50  fn from_css(input: &mut Parser<'i, '_>) -> ParseResult<'i, Self> {
51    if input.try_parse(|i| i.expect_ident_matching("none")).is_ok() {
52      return Ok(LineClamp {
53        count: 0,
54        ellipsis: None,
55      });
56    }
57    let count = input.try_parse(Parser::expect_integer)?;
58    let ellipsis = input.try_parse(Parser::expect_string_cloned).ok();
59
60    Ok(LineClamp {
61      count: count as u32,
62      ellipsis: ellipsis.map(|s| s.to_string()),
63    })
64  }
65
66  const VALID_TOKENS: &'static [CssToken] = &[
67    CssToken::Keyword("none"),
68    CssToken::Syntax(CssSyntaxKind::Integer),
69    CssToken::Syntax(CssSyntaxKind::String),
70  ];
71}
72
73impl ToCss for LineClamp {
74  fn to_css<W: fmt::Write>(&self, dest: &mut W) -> fmt::Result {
75    if self.count == 0 && self.ellipsis.is_none() {
76      return dest.write_str("none");
77    }
78    match &self.ellipsis {
79      Some(e) => {
80        write!(dest, "{} ", self.count)?;
81        write_css_string(dest, e)
82      }
83      None => write!(dest, "{}", self.count),
84    }
85  }
86}