1use nom::branch::alt;
13use nom::bytes::complete::tag;
14use nom::combinator::peek;
15use nom::error::ParseError;
16use nom::multi::{many0, many1};
17use nom::sequence::{terminated, tuple};
18use nom::{IResult, Parser};
19
20use super::flat_ruleset::FlatRuleset;
21use super::ruleset::{QualNestedRuleset, QualRule, QualRuleset, Rule, Ruleset, SelectorRuleset};
22use super::selector::Selector;
23use super::token::{comment0, sep0};
24use crate::parser::*;
25use crate::render::*;
26use crate::transform::TransformCss;
27
28#[derive(Clone, Debug, Eq, PartialEq, Hash)]
32pub enum TreeRule<'a> {
33 Rule(Rule<'a>),
34 Ruleset(TreeRuleset<'a>),
35}
36
37impl<'a> ParseCss<'a> for TreeRule<'a> {
38 fn parse<E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, Self, E> {
39 let block = terminated(TreeRuleset::parse, sep0).map(TreeRule::Ruleset);
40 let rule = terminated(Rule::parse, sep0).map(TreeRule::Rule);
41 alt((block, rule))(input)
42 }
43}
44
45impl<'a> RenderCss for TreeRule<'a> {
46 fn render(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
47 match self {
48 TreeRule::Rule(rule) => rule.render(f),
49 TreeRule::Ruleset(block) => block.render(f),
50 }
51 }
52}
53
54impl<'a> TransformCss<Rule<'a>> for TreeRule<'a> {
55 fn transform_each<F: FnMut(&mut Rule<'a>)>(&mut self, f: &mut F) {
56 match self {
57 TreeRule::Rule(rule) => f(rule),
58 TreeRule::Ruleset(ruleset) => ruleset.transform_each(f),
59 }
60 }
61}
62
63impl<'a> TransformCss<TreeRuleset<'a>> for TreeRule<'a> {
64 fn transform_each<F: FnMut(&mut TreeRuleset<'a>)>(&mut self, f: &mut F) {
65 match self {
66 TreeRule::Rule(_) => (),
67 TreeRule::Ruleset(ruleset) => ruleset.transform_each(f),
68 }
69 }
70}
71
72impl<'a> TransformCss<Vec<TreeRuleset<'a>>> for TreeRule<'a> {
73 fn transform_each<F: FnMut(&mut Vec<TreeRuleset<'a>>)>(&mut self, f: &mut F) {
74 match self {
75 TreeRule::Rule(_) => (),
76 TreeRule::Ruleset(ruleset) => ruleset.transform_each(f),
77 }
78 }
79}
80
81pub type TreeRuleset<'a> = Ruleset<'a, TreeRule<'a>>;
96
97impl<'a> ParseCss<'a> for TreeRuleset<'a> {
98 fn parse<E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, Self, E> {
99 if let Ok((input, _)) = peek::<_, _, E, _>(tag("@"))(input) {
100 let (input, qual_rule) = QualRule::parse(input)?;
101 if let Ok((input, _)) = tag::<_, _, E>(";")(input) {
102 Ok((input, Ruleset::QualRule(qual_rule)))
103 } else {
104 let (input, _) = tuple((tag("{"), sep0))(input)?;
105 let (input, rules) = many1(TreeRule::parse::<E>)(input)?;
106 let (input, _) = tuple((comment0, tag("}")))(input)?;
107 Ok((input, Ruleset::QualRuleset(QualRuleset(qual_rule, rules))))
108 }
109 } else {
110 let (input, selector_ruleset) = SelectorRuleset::parse(input)?;
111 Ok((input, Ruleset::SelectorRuleset(selector_ruleset)))
112 }
113 }
114}
115
116impl<'a> TransformCss<TreeRuleset<'a>> for TreeRuleset<'a> {
117 fn transform_each<F: FnMut(&mut TreeRuleset<'a>)>(&mut self, f: &mut F) {
118 f(self);
119 match self {
120 Ruleset::QualRule(_) => (),
121 Ruleset::QualRuleset(_) => (),
122 Ruleset::QualNestedRuleset(..) => (),
123 Ruleset::SelectorRuleset(ruleset) => {
124 for rule in ruleset.1.iter_mut() {
125 rule.transform_each(f)
126 }
127 }
128 }
129 }
130}
131
132impl<'a> TreeRuleset<'a> {
133 pub fn flatten_tree(&self) -> Vec<FlatRuleset<'a>> {
137 match self {
138 Ruleset::SelectorRuleset(ruleset) => ruleset.flatten_tree(),
139 Ruleset::QualRule(x) => vec![Ruleset::QualRule(x.clone())],
140 Ruleset::QualRuleset(rules) => {
141 let mut new_rules: Vec<Rule<'a>> = vec![];
142 let mut new_rulesets: Vec<FlatRuleset<'a>> = vec![];
143 for rule in rules.1.iter() {
144 match rule {
145 TreeRule::Rule(rule) => new_rules.push(rule.clone()),
146 TreeRule::Ruleset(ruleset) => {
147 let sub_rules = ruleset.flatten_tree().into_iter();
148 new_rulesets.extend(sub_rules)
149 }
150 }
151 }
152
153 let mut ret = vec![];
154 if !new_rules.is_empty() {
155 let ruleset = QualRuleset(rules.0.clone(), new_rules);
156 ret.push(Ruleset::QualRuleset(ruleset));
157 }
158
159 if !new_rulesets.is_empty() {
160 ret.push(Ruleset::QualNestedRuleset(QualNestedRuleset(
161 rules.0.clone(),
162 new_rulesets,
163 )))
164 }
165
166 ret
167 }
168 Ruleset::QualNestedRuleset(ruleset) => {
169 vec![Ruleset::QualNestedRuleset(QualNestedRuleset(
170 ruleset.0.clone(),
171 ruleset.1.iter().flat_map(|x| x.flatten_tree()).collect(),
172 ))]
173 }
174 }
175 }
176}
177
178type TreeSelectorRuleset<'a> = SelectorRuleset<'a, TreeRule<'a>>;
179
180impl<'a> ParseCss<'a> for TreeSelectorRuleset<'a> {
181 fn parse<E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, Self, E> {
182 let (input, selector) = Selector::parse(input)?;
183 let (input, _) = tuple((comment0, tag("{"), sep0))(input)?;
184 let (input, rules) = many0(TreeRule::parse)(input)?;
185 let (input, _) = tuple((comment0, tag("}")))(input)?;
186 Ok((input, SelectorRuleset(selector, rules)))
187 }
188}
189
190impl<'a> TransformCss<Vec<TreeRuleset<'a>>> for TreeRuleset<'a> {
191 fn transform_each<F: FnMut(&mut Vec<TreeRuleset<'a>>)>(&mut self, f: &mut F) {
192 match self {
193 Ruleset::SelectorRuleset(ruleset) => {
194 for rule in ruleset.1.iter_mut() {
195 rule.transform_each(f)
196 }
197 }
198 Ruleset::QualRule(_) => (),
199 Ruleset::QualRuleset(_) => (),
200 Ruleset::QualNestedRuleset(ruleset) => {
201 for rule in ruleset.1.iter_mut() {
202 rule.transform_each(f)
203 }
204 }
205 }
206 }
207}
208
209impl<'a> TreeSelectorRuleset<'a> {
210 pub fn flatten_tree(&self) -> Vec<Ruleset<'a, Rule<'a>>> {
213 let mut new_rules: Vec<Rule<'a>> = vec![];
214 let mut new_rulesets: Vec<FlatRuleset<'a>> = vec![];
215 for rule in self.1.iter() {
216 match rule {
217 TreeRule::Rule(rule) => new_rules.push(rule.clone()),
218 TreeRule::Ruleset(ruleset) => {
219 if !new_rules.is_empty() {
220 let ruleset = SelectorRuleset(self.0.clone(), new_rules);
221 new_rulesets.push(Ruleset::SelectorRuleset(ruleset));
222 new_rules = vec![];
223 }
224
225 let sub_rules = ruleset
226 .flatten_tree()
227 .into_iter()
228 .map(|ruleset| self.join(ruleset));
229 new_rulesets.extend(sub_rules)
230 }
231 }
232 }
233
234 if !new_rules.is_empty() {
235 let ruleset = SelectorRuleset(self.0.clone(), new_rules);
236 new_rulesets.push(Ruleset::SelectorRuleset(ruleset));
237 }
238
239 new_rulesets
240 }
241
242 fn join(&self, rhs: Ruleset<'a, Rule<'a>>) -> Ruleset<'a, Rule<'a>> {
244 match rhs {
245 Ruleset::SelectorRuleset(inner_ruleset) => {
246 let joined_selector = self.0.join(&inner_ruleset.0);
247 Ruleset::SelectorRuleset(SelectorRuleset(joined_selector, inner_ruleset.1))
248 }
249 ruleset => ruleset,
250 }
251 }
252}