css_ast/rules/
charset.rs

1use crate::diagnostics;
2use css_parse::{Cursor, Parse, Parser, Result as ParserResult, T};
3use csskit_derives::{ToCursors, ToSpan, Visitable};
4
5// https://drafts.csswg.org/css-syntax-3/#charset-rule
6#[derive(ToSpan, ToCursors, Visitable, Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
7#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
8#[cfg_attr(feature = "css_feature_data", derive(::csskit_derives::ToCSSFeature), css_feature("css.at-rules.charset"))]
9#[visit(self)]
10pub struct CharsetRule {
11	at_keyword: T![AtKeyword],
12	space: T![' '],
13	string: T![String],
14	semicolon: Option<T![;]>,
15}
16
17// CharsetRule is a special rule which means it cannot use standard AtRule parsing... comments below
18// https://drafts.csswg.org/css-syntax-3/#determine-the-fallback-encoding
19impl<'a> Parse<'a> for CharsetRule {
20	fn parse(p: &mut Parser<'a>) -> ParserResult<Self> {
21		let at_keyword = p.parse::<T![AtKeyword]>()?;
22		let c: Cursor = at_keyword.into();
23		// CharsetRule MUST be all lowercase, alt cases such as CHARSET or charSet aren't
24		// valid here, compares to other at-rules which are case insensitive.
25		if !p.eq_ignore_ascii_case(c, "charset") {
26			Err(diagnostics::UnexpectedAtRule(p.parse_str(c).into(), c))?;
27		}
28		// Charsets MUST have a space between the at keyword and the string. This
29		// isn't necessary in other at rules where an at keyword can align with other
30		// delims (e.g. `(`) or unambinguous tokens like strings.
31		let space = p.parse::<T![' ']>()?;
32		let string = p.parse::<T![String]>()?;
33		// TODO: check quote style as it should be "
34		let semicolon = p.parse::<T![;]>().ok();
35		Ok(Self { at_keyword, space, string, semicolon })
36	}
37}
38
39#[cfg(test)]
40mod tests {
41	use super::*;
42	use css_parse::assert_parse;
43
44	#[test]
45	fn size_test() {
46		assert_eq!(std::mem::size_of::<CharsetRule>(), 52);
47	}
48
49	#[test]
50	fn test_writes() {
51		assert_parse!(CharsetRule, "@charset \"utf-8\";", "@charset \"utf-8\";");
52		assert_parse!(CharsetRule, "@charset \"UTF-8\";", "@charset \"UTF-8\";");
53	}
54}