use cssparser::Token; pub(crate) fn render_token(token: &Token<'_>) -> String { match token { Token::Ident(ident) => ident.to_string(), Token::AtKeyword(value) => format!("@{value}"), Token::Hash(name) | Token::IDHash(name) => format!("#{name}"), Token::QuotedString(value) => format!("\"{value}\""), Token::UnquotedUrl(value) => value.to_string(), Token::Number { has_sign: signed, value: num, int_value: _, } | Token::Percentage { has_sign: signed, unit_value: num, int_value: _, } => render_number(*signed, *num, token), Token::Dimension { has_sign: signed, value: num, int_value: _, unit, } => format!("{}{}", render_int(*signed, *num), unit), Token::WhiteSpace(_) => String::from(" "), Token::Comment(comment) => format!("/* {comment} */"), Token::Function(name) => format!("{name}()"), Token::BadString(string) => format!(""), Token::BadUrl(url) => format!(""), // Single-character token Token::Colon => ":".into(), Token::Semicolon => ";".into(), Token::Comma => ",".into(), Token::IncludeMatch => "~=".into(), Token::DashMatch => "|=".into(), Token::PrefixMatch => "^=".into(), Token::SuffixMatch => "$=".into(), Token::SubstringMatch => "*=".into(), Token::CDO => "".into(), Token::ParenthesisBlock => "<(".into(), Token::SquareBracketBlock => "<[".into(), Token::CurlyBracketBlock => "<{".into(), Token::CloseParenthesis => "<)".into(), Token::CloseSquareBracket => "<]".into(), Token::CloseCurlyBracket => "<}".into(), Token::Delim(delim) => (*delim).into(), } } fn render_number(signed: bool, num: f32, token: &Token) -> String { let num = render_int(signed, num); match token { Token::Number { .. } => num, Token::Percentage { .. } => format!("{num}%"), _ => panic!("render_number is not supposed to be called on a non-numerical token"), } } fn render_int(signed: bool, num: f32) -> String { if signed { render_int_signed(num) } else { render_int_unsigned(num) } } fn render_int_signed(num: f32) -> String { if num > 0.0 { format!("+{num}") } else { format!("-{num}") } } fn render_int_unsigned(num: f32) -> String { format!("{num}") } #[cfg(test)] mod tests { use crate::Selector; #[test] fn regression_test_issue212() { let err = Selector::parse("div138293@!#@!!@#").unwrap_err(); assert_eq!(err.to_string(), "Token \"@\" was not expected"); } }