Skip to main content

takumi_css/style/properties/grid/
grid_line.rs

1use cssparser::Parser;
2
3use crate::style::{
4  CssSyntaxKind, CssToken, FromCss, GridPlacementSpan, MakeComputed, ParseResult, SizingContext,
5  tw::TailwindPropertyParser,
6};
7
8use crate::style::GridPlacement;
9
10/// Represents a grid line placement with serde support
11#[derive(Debug, Clone, Default, PartialEq)]
12#[non_exhaustive]
13pub struct GridLine {
14  /// The start line placement
15  pub start: GridPlacement,
16  /// The end line placement
17  pub end: GridPlacement,
18}
19
20impl MakeComputed for GridLine {
21  fn make_computed(&mut self, sizing: &SizingContext) {
22    self.start.make_computed(sizing);
23    self.end.make_computed(sizing);
24  }
25}
26
27impl GridLine {
28  /// Create a grid line that spans the entire grid
29  pub const fn full() -> Self {
30    Self {
31      start: GridPlacement::Line(1),
32      end: GridPlacement::Line(-1),
33    }
34  }
35
36  /// Create a grid line with a span placement
37  pub const fn span(span: GridPlacementSpan) -> Self {
38    Self {
39      start: GridPlacement::Span(span),
40      end: GridPlacement::Span(span),
41    }
42  }
43}
44
45impl<'i> FromCss<'i> for GridLine {
46  fn from_css(input: &mut Parser<'i, '_>) -> ParseResult<'i, Self> {
47    // First placement is required
48    let first = GridPlacement::from_css(input)?;
49
50    // Optional delimiter '/'
51    let second = if input.try_parse(|i| i.expect_delim('/')).is_ok() {
52      Some(GridPlacement::from_css(input)?)
53    } else {
54      None
55    };
56
57    Ok(GridLine {
58      start: first,
59      end: second.unwrap_or_default(),
60    })
61  }
62
63  const VALID_TOKENS: &'static [CssToken] = &[
64    CssToken::Keyword("span"),
65    CssToken::Syntax(CssSyntaxKind::Number),
66    CssToken::Syntax(CssSyntaxKind::Ident),
67  ];
68}
69
70impl TailwindPropertyParser for GridLine {
71  fn parse_tw(suffix: &str) -> Option<Self> {
72    if suffix.eq_ignore_ascii_case("auto") {
73      return Some(GridLine {
74        start: GridPlacement::auto(),
75        end: GridPlacement::auto(),
76      });
77    }
78    let number = suffix.parse::<i16>().ok()?;
79
80    Some(GridLine {
81      start: GridPlacement::Line(number),
82      end: GridPlacement::auto(),
83    })
84  }
85}
86
87#[cfg(test)]
88mod tests {
89  use super::*;
90
91  #[test]
92  fn test_parse_line() {
93    assert_eq!(
94      GridLine::from_str("span 2 / 3"),
95      Ok(GridLine {
96        start: GridPlacement::span(2),
97        end: GridPlacement::Line(3),
98      })
99    );
100  }
101}