diff --git a/src/selector/mod.rs b/src/selector/mod.rs index e04b3eb..7773951 100644 --- a/src/selector/mod.rs +++ b/src/selector/mod.rs @@ -490,7 +490,57 @@ impl Selector { } pub fn remove_placeholders(self) -> Selector { - Selector(self.0.into_iter().filter(|s| !s.is_invisible).collect()) + Selector( + self.0 + .into_iter() + .filter_map(|s| { + if s.is_invisible { + None + } else { + let mut inner = Vec::new(); + let mut last_was_whitespace = false; + let len = s.inner.len(); + for kind in s.inner { + match kind { + SelectorKind::PseudoParen(name, inner_selector) => { + let inner_empty = inner_selector.is_empty(); + let removed_placeholders = inner_selector.remove_placeholders(); + if removed_placeholders.is_empty() && !inner_empty { + if name.to_ascii_lowercase().as_str() == "not" { + if last_was_whitespace || len == 1 { + inner.push(SelectorKind::Universal); + } else { + continue; + } + } else { + return None; + } + } else { + inner.push(SelectorKind::PseudoParen( + name, + removed_placeholders, + )); + } + } + SelectorKind::Whitespace => { + last_was_whitespace = true; + inner.push(kind); + continue; + } + _ => inner.push(kind), + } + last_was_whitespace = false; + } + Some(SelectorPart { + inner, + is_invisible: false, + has_newline: s.has_newline, + contains_super_selector: s.contains_super_selector, + }) + } + }) + .collect(), + ) } pub fn is_empty(&self) -> bool { diff --git a/tests/selectors.rs b/tests/selectors.rs index 03587d6..291c3a1 100644 --- a/tests/selectors.rs +++ b/tests/selectors.rs @@ -368,3 +368,37 @@ test!( ".foo,\n.bar {\n .baz & {\n color: red;\n }\n}\n", ".baz .foo,\n.baz .bar {\n color: red;\n}\n" ); +test!( + not_only_placeholder_is_universal, + "a :not(%b) {x: y}", + "a * {\n x: y;\n}\n" +); +test!( + not_placeholder_is_removed, + "a:not(%b, c) {x: y}", + "a:not(c) {\n x: y;\n}\n" +); +test!( + psuedo_paren_removes_inner_placeholder, + "a:matches(%b, c) {x: y}", + "a:matches(c) {\n x: y;\n}\n" +); +test!( + matches_placeholder_removes_everything, + "a:matches(%b) {x: y}", + "" +); +test!( + touching_universal_stays_the_same, + "a* {\n color: red;\n}\n" +); +test!( + adjacent_not_placeholder_is_ignored, + "a:not(%b) {x: y}", + "a {\n x: y;\n}\n" +); +test!( + pseudo_paren_placeholder_alone, + ":not(%b) {x: y}", + "* {\n x: y;\n}\n" +);