1use crate::css::{self, parser::selector_set};
10use crate::parser::input_span;
11use crate::sass::SassString;
12use crate::{Error, ParseError, ScopeRef};
13use std::fmt::Write;
14
15#[derive(Clone, Debug, PartialEq, Eq, PartialOrd)]
17pub struct Selectors {
18 s: Vec<Selector>,
20}
21
22impl Selectors {
23 pub fn root() -> Self {
25 Self::new(vec![Selector::root()])
26 }
27 pub fn is_root(&self) -> bool {
29 self.s == [Selector::root()]
30 }
31 pub fn new(s: Vec<Selector>) -> Self {
33 Self { s }
34 }
35
36 pub fn eval(&self, scope: ScopeRef) -> Result<css::SelectorSet, Error> {
38 let mut s = Vec::new();
39 for sel in &self.s {
40 s.extend(sel.eval(scope.clone())?);
41 }
42 Ok(css::SelectorSet { s })
43 }
44 fn write_eval(
45 &self,
46 f: &mut String,
47 scope: ScopeRef,
48 ) -> Result<(), Error> {
49 if let Some((first, rest)) = self.s.split_first() {
50 first.write_eval(f, scope.clone())?;
51 for s in rest {
52 f.push_str(", ");
53 s.write_eval(f, scope.clone())?;
54 }
55 }
56 Ok(())
57 }
58}
59
60#[derive(Clone, Debug, PartialEq, Eq, PartialOrd)]
65pub struct Selector(Vec<SelectorPart>);
66
67impl Selector {
68 pub fn root() -> Self {
70 Self(vec![])
71 }
72 pub fn new(s: Vec<SelectorPart>) -> Self {
74 Self(s)
75 }
76 fn eval(&self, scope: ScopeRef) -> Result<Vec<css::Selector>, Error> {
77 if self.0.is_empty() {
78 Ok(vec![css::Selector::default()])
79 } else {
80 let mut text = String::new();
81 self.write_eval(&mut text, scope)?;
82 Ok(ParseError::check(selector_set(input_span(text).borrow()))?.s)
83 }
84 }
85
86 fn write_eval(
87 &self,
88 f: &mut String,
89 scope: ScopeRef,
90 ) -> Result<(), Error> {
91 for p in &self.0 {
92 p.write_eval(f, scope.clone())?;
93 }
94 Ok(())
95 }
96}
97
98#[derive(Clone, Debug, PartialEq, Eq, PartialOrd)]
100pub enum SelectorPart {
101 Simple(SassString),
106 Descendant,
110 RelOp(u8),
112 Attribute {
114 name: SassString,
116 op: String,
118 val: SassString,
120 modifier: Option<char>,
122 },
123 PseudoElement {
125 name: SassString,
127 arg: Option<Selectors>,
129 },
130 Pseudo {
132 name: SassString,
134 arg: Option<Selectors>,
136 },
137 BackRef,
139}
140
141impl SelectorPart {
142 fn write_eval(
143 &self,
144 f: &mut String,
145 scope: ScopeRef,
146 ) -> Result<(), Error> {
147 match self {
148 SelectorPart::Simple(s) => we(s, f, scope)?,
149 SelectorPart::Descendant => f.push(' '),
150 SelectorPart::RelOp(op) => {
151 if let Some(ch) = char::from_u32(u32::from(*op)) {
152 f.push(' ');
153 f.push(ch);
154 f.push(' ');
155 }
156 }
157 SelectorPart::Attribute {
158 name,
159 op,
160 val,
161 modifier,
162 } => {
163 f.push('[');
164 we(name, f, scope.clone())?;
165 f.push_str(op);
166 let val = val.evaluate(scope)?.opt_unquote();
167 write!(f, "{val}")?;
168 if let Some(modifier) = modifier {
169 if val.quotes().is_none() {
170 f.push(' ');
171 }
172 f.push(*modifier);
173 }
174 f.push(']');
175 }
176 SelectorPart::PseudoElement { name, arg } => {
177 f.push_str("::");
178 we(name, f, scope.clone())?;
179 if let Some(arg) = arg {
180 f.push('(');
181 arg.write_eval(f, scope)?;
182 f.push(')');
183 }
184 }
185 SelectorPart::Pseudo { name, arg } => {
186 f.push(':');
187 we(name, f, scope.clone())?;
188 if let Some(arg) = arg {
189 f.push('(');
190 arg.write_eval(f, scope)?;
191 f.push(')');
192 }
193 }
194 SelectorPart::BackRef => f.push('&'),
195 }
196 Ok(())
197 }
198}
199
200fn we(s: &SassString, f: &mut String, scope: ScopeRef) -> Result<(), Error> {
201 write!(f, "{}", s.evaluate(scope)?)?;
202 Ok(())
203}