Skip to main content

css_parse/syntax/
bang_important.rs

1use super::prelude::*;
2
3/// Represents a two tokens, the first being [Kind::Delim] where the char is `!`, and the second being an `Ident` with
4/// the value `important`. [CSS defines this as]:
5///
6/// ```md
7/// <ws*>
8///     ╭──────────────────────────╮
9///  │├─╯─╭─ <whitespace-token> ─╮─╰─┤│
10///       ╰──────────────────────╯
11///
12/// <!important>
13///  │├─ "!" ─ <ws*> ─ <ident-token "important"> ─ <ws*> ─┤│
14/// ```
15///
16/// `<ws*>` is any number of `<whitespace-token>`s, defined as [Kind::Whitespace][Kind::Whitespace]. This is
17/// automatically skipped by default in the [Parser] anyway.
18///
19/// [1]: https://drafts.csswg.org/css-syntax-3/#!important-diagram
20///
21#[node]
22#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
23#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
24pub struct BangImportant {
25	pub bang: T![!],
26	pub important: T![Ident],
27}
28
29impl<'a> Peek<'a> for BangImportant {
30	const PEEK_KINDSET: KindSet = KindSet::new(&[Kind::Delim]);
31
32	#[inline(always)]
33	fn peek<Iter>(p: &Parser<'a, Iter>, c: Cursor) -> bool
34	where
35		Iter: Iterator<Item = Cursor> + Clone,
36	{
37		if c == Kind::Delim && c == '!' {
38			let c = p.peek_n(2);
39			c == Kind::Ident && p.to_source_cursor(c).eq_ignore_ascii_case("important")
40		} else {
41			false
42		}
43	}
44}
45
46impl<'a> Parse<'a> for BangImportant {
47	fn parse<Iter>(p: &mut Parser<'a, Iter>) -> Result<Self>
48	where
49		Iter: Iterator<Item = Cursor> + Clone,
50	{
51		let bang = p.parse::<T![!]>()?;
52		let important = p.parse::<T![Ident]>()?;
53		if !p.to_source_cursor(important.into()).eq_ignore_ascii_case("important") {
54			Err(Diagnostic::new(important.into(), Diagnostic::unexpected_ident))?
55		}
56		Ok(Self { bang, important })
57	}
58}
59
60impl ToCursors for BangImportant {
61	fn to_cursors(&self, s: &mut impl CursorSink) {
62		s.append(self.bang.into());
63		s.append(self.important.into());
64	}
65}
66
67impl ToSpan for BangImportant {
68	fn to_span(&self) -> Span {
69		self.bang.to_span() + self.important.to_span()
70	}
71}
72
73impl SemanticEq for BangImportant {
74	fn semantic_eq(&self, _: &Self, _source_text: &str) -> bool {
75		// The presence of !important is semantic in of itself, so this is just always true
76		true
77	}
78}