rust_less/selects/
select.rs

1use pest::iterators::Pair;
2use crate::parser::Rule;
3use crate::utils::{get_attr_and_variable, get_select_name};
4use crate::selects::{Attr, Variable, ToCss};
5
6#[derive(Debug)]
7pub struct Select {
8    pub select_name: String,
9    pub select_value: String,
10    pub span: (usize, usize),
11    pub attr_list: Vec<Attr>,
12    pub variable_list: Vec<Variable>,
13    pub children: Box<Vec<Select>>,
14    pub parent_select_names: Vec<String>,
15    pub ancestor_variable_list: Vec<Variable>,
16}
17
18impl Select {
19    pub fn new(pair: &Pair<Rule>, parents: Vec<String>, ancestor_variable_list: Vec<Variable>) -> Self {
20        let rule = pair.as_rule();
21        if rule != Rule::select {
22            panic!("Not a select");
23        } else {
24            let select_name = get_select_name(&pair);
25
26            let span = (pair.as_span().start(), pair.as_span().end());
27
28            let child_pairs = pair.clone().into_inner();
29
30            let mut children = vec![];
31
32            let (attr_list, variable_list) = get_attr_and_variable(pair);
33
34            for child_pair in child_pairs {
35                if child_pair.as_rule() == Rule::select {
36                    let mut p = parents.clone();
37                    p.push(select_name.clone());
38
39                    let mut new_ancestor_variable_list = vec![];
40                    for item in ancestor_variable_list.clone() {
41                        new_ancestor_variable_list.insert(0, item);
42                    }
43
44                    for item in variable_list.clone() {
45                        new_ancestor_variable_list.insert(0, item);
46                    }
47
48                    children.push(Select::new(&child_pair, p, new_ancestor_variable_list));
49                }
50            }
51
52            let select = Select {
53                select_name,
54                span,
55                select_value: pair.as_span().as_str().to_string(),
56                children: Box::new(children),
57                parent_select_names: parents.clone(),
58                variable_list,
59                attr_list,
60                ancestor_variable_list,
61            };
62            return select;
63        }
64    }
65
66    pub fn clear_value(&mut self) {
67        let mut need_removes: Vec<(usize, usize)> = vec![];
68        for child in self.children.as_mut_slice() {
69            let remove = (child.span.0 - self.span.0, child.span.1 - self.span.0);
70            need_removes.push(remove);
71            child.clear_value();
72        }
73
74        let mut diff = 0;
75        for (mut start, mut end) in need_removes {
76            start = start - diff;
77            end = end - diff;
78            diff = diff + end - start;
79            self.select_value.replace_range(start..end, "");
80        }
81    }
82
83    pub fn find_variable(&self, name: &str) -> Option<String> {
84        let variable_list = &self.variable_list;
85        let ancestor_variable_list = &self.ancestor_variable_list;
86
87        let result = variable_list.iter().find(|&item| {
88            if item.0 == *name {
89                return true;
90            }
91            return false;
92        });
93
94        if let Some(res) = result {
95            return Some(res.1.clone());
96        } else {
97            let result = ancestor_variable_list.iter().find(|&item| {
98                if item.0 == *name {
99                    return true;
100                }
101                return false;
102            });
103            if let Some(res) = result {
104                Some(res.1.clone())
105            } else {
106                None
107            }
108        }
109    }
110}
111
112impl ToCss for Select {
113    fn to_css(&self) -> String {
114        let mut result = String::from("");
115
116        let mut full_class_name = String::from("");
117        let parent_class_name = self.parent_select_names.join(" ");
118        if self.select_name.contains('&') && &self.select_name != "&" {
119            full_class_name.push_str(&self.select_name.replace("&", &parent_class_name));
120        } else {
121            full_class_name.push_str(&parent_class_name);
122            if self.parent_select_names.len() > 0 {
123                full_class_name.push(' ');
124            }
125            full_class_name.push_str(&self.select_name);
126        }
127
128        let mut value = String::from("");
129
130        value.push_str(&full_class_name);
131        value.push(' ');
132        value.push('{');
133        value.push('\n');
134
135        for attr in &self.attr_list {
136            let mut attr_s = String::from("  ");
137            attr_s.push_str(&attr.0);
138            attr_s.push_str(": ");
139            if let Some(res) = self.find_variable(&attr.1) {
140                attr_s.push_str(&res);
141            } else {
142                attr_s.push_str(&attr.1);
143            }
144            attr_s.push_str(";\n");
145
146            value.push_str(&attr_s);
147        }
148
149        value.push_str("}\n");
150
151        result.push_str(&value);
152
153        result.push('\n');
154
155        for child in self.children.as_slice() {
156            result.push_str(&child.to_css());
157        }
158
159        return result;
160    }
161}