From 5c61f8ccaa078afa6eb0379f2a873af37a8416a9 Mon Sep 17 00:00:00 2001 From: Connor Skees Date: Sun, 4 Jul 2021 11:48:13 -0400 Subject: [PATCH] :is is alias for :matches --- src/selector/extend/mod.rs | 5 +++-- src/selector/parse.rs | 3 ++- src/selector/simple.rs | 4 ++-- tests/selector-extend.rs | 15 +++++++++++++++ tests/selector-nest.rs | 21 ++++++++++++++++++--- tests/selector-parse.rs | 5 +++++ tests/selector-replace.rs | 5 +++++ tests/selector-unify.rs | 10 ++++++++++ tests/selectors.rs | 10 ++++++++-- 9 files changed, 68 insertions(+), 10 deletions(-) diff --git a/src/selector/extend/mod.rs b/src/selector/extend/mod.rs index db4c70a..0b6f5af 100644 --- a/src/selector/extend/mod.rs +++ b/src/selector/extend/mod.rs @@ -656,13 +656,14 @@ impl Extender { // become `.foo:not(.bar)`. However, this is a narrow edge case and // supporting it properly would make this code and the code calling it // a lot more complicated, so it's not supported for now. - if inner_pseudo.normalized_name() == "matches" { + let inner_pseudo_normalized = inner_pseudo.normalized_name(); + if inner_pseudo_normalized == "matches" || inner_pseudo_normalized == "is" { inner_pseudo.selector.clone().unwrap().components } else { Vec::new() } } - "matches" | "any" | "current" | "nth-child" | "nth-last-child" => { + "matches" | "is" | "any" | "current" | "nth-child" | "nth-last-child" => { // As above, we could theoretically support :not within :matches, but // doing so would require this method and its callers to handle much // more complex cases that likely aren't worth the pain. diff --git a/src/selector/parse.rs b/src/selector/parse.rs index ea2cad4..93d5d2e 100644 --- a/src/selector/parse.rs +++ b/src/selector/parse.rs @@ -36,9 +36,10 @@ impl DevouredWhitespace { } /// Pseudo-class selectors that take unadorned selectors as arguments. -const SELECTOR_PSEUDO_CLASSES: [&str; 7] = [ +const SELECTOR_PSEUDO_CLASSES: [&str; 8] = [ "not", "matches", + "is", "current", "any", "has", diff --git a/src/selector/simple.rs b/src/selector/simple.rs index ae381d9..f4fa434 100644 --- a/src/selector/simple.rs +++ b/src/selector/simple.rs @@ -12,7 +12,7 @@ use super::{ QualifiedName, SelectorList, Specificity, }; -const SUBSELECTOR_PSEUDOS: [&str; 4] = ["matches", "any", "nth-child", "nth-last-child"]; +const SUBSELECTOR_PSEUDOS: [&str; 5] = ["matches", "is", "any", "nth-child", "nth-last-child"]; const BASE_SPECIFICITY: i32 = 1000; @@ -487,7 +487,7 @@ impl Pseudo { ) -> bool { debug_assert!(self.selector.is_some()); match self.normalized_name() { - "matches" | "any" => { + "matches" | "is" | "any" => { let pseudos = selector_pseudos_named(compound.clone(), &self.name, true); pseudos.iter().any(move |pseudo2| { self.selector diff --git a/tests/selector-extend.rs b/tests/selector-extend.rs index b384cec..d0972d5 100644 --- a/tests/selector-extend.rs +++ b/tests/selector-extend.rs @@ -296,6 +296,21 @@ test!( "a {\n color: selector-extend(\":not(.c)\", \".c\", \".d:matches(.e, .f)\");\n}\n", "a {\n color: :not(.c):not(.d:matches(.e, .f));\n}\n" ); +test!( + simple_pseudo_idempotent_not_and_is_list, + "a {\n color: selector-extend(\":not(.c)\", \".c\", \":is(.d, .e)\");\n}\n", + "a {\n color: :not(.c):not(.d):not(.e);\n}\n" +); +test!( + simple_pseudo_idempotent_not_and_is_list_of_complex, + "a {\n color: selector-extend(\":not(.c)\", \".c\", \":is(.d .e, .f .g)\");\n}\n", + "a {\n color: :not(.c):not(.d .e):not(.f .g);\n}\n" +); +test!( + simple_pseudo_idempotent_not_and_is_in_compound, + "a {\n color: selector-extend(\":not(.c)\", \".c\", \".d:is(.e, .f)\");\n}\n", + "a {\n color: :not(.c):not(.d:is(.e, .f));\n}\n" +); test!( simple_pseudo_idempotent_not_and_not_in_extender, "a {\n color: selector-extend(\":not(.c)\", \".c\", \":not(.d)\");\n}\n", diff --git a/tests/selector-nest.rs b/tests/selector-nest.rs index fc72acb..bb42314 100644 --- a/tests/selector-nest.rs +++ b/tests/selector-nest.rs @@ -37,15 +37,25 @@ test!( "a {\n color: e c d.f;\n}\n" ); test!( - nest_parent_in_special_pseudo, + nest_parent_in_special_pseudo_matches, "a {\n color: selector-nest(\"c\", \":matches(&)\");\n}\n", "a {\n color: :matches(c);\n}\n" ); test!( - nest_complex_super_parent_in_special_pseudo, + nest_complex_super_parent_in_special_pseudo_matches, "a {\n color: selector-nest(\"c d\", \":matches(&)\");\n}\n", "a {\n color: :matches(c d);\n}\n" ); +test!( + nest_parent_in_special_pseudo_is, + "a {\n color: selector-nest(\"c\", \":is(&)\");\n}\n", + "a {\n color: :is(c);\n}\n" +); +test!( + nest_complex_super_parent_in_special_pseudo_is, + "a {\n color: selector-nest(\"c d\", \":is(&)\");\n}\n", + "a {\n color: :is(c d);\n}\n" +); test!( nest_multiple_parent, "a {\n color: selector-nest(\"c\", \"&.d &.e\");\n}\n", @@ -92,10 +102,15 @@ test!( "a {\n color: e c.f, e d.f;\n}\n" ); test!( - nest_super_list_parent_inside_pseudo, + nest_super_list_parent_inside_pseudo_matches, "a {\n color: selector-nest(\"c, d\", \":matches(&)\");\n}\n", "a {\n color: :matches(c, d);\n}\n" ); +test!( + nest_super_list_parent_inside_pseudo_is, + "a {\n color: selector-nest(\"c, d\", \":is(&)\");\n}\n", + "a {\n color: :is(c, d);\n}\n" +); test!( nest_super_list_multiple_parent, "a {\n color: selector-nest(\"c, d\", \"&.e &.f\");\n}\n", diff --git a/tests/selector-parse.rs b/tests/selector-parse.rs index c9a5dba..4d8cc22 100644 --- a/tests/selector-parse.rs +++ b/tests/selector-parse.rs @@ -46,6 +46,11 @@ test!( "a {\n color: selector-parse(\":matches(b, c)\");\n}\n", "a {\n color: :matches(b, c);\n}\n" ); +test!( + pseudo_is_with_list_args, + "a {\n color: selector-parse(\":is(b, c)\");\n}\n", + "a {\n color: :is(b, c);\n}\n" +); test!( pseudo_element, "a {\n color: selector-parse(\"::c\");\n}\n", diff --git a/tests/selector-replace.rs b/tests/selector-replace.rs index 6202e30..3ad1b77 100644 --- a/tests/selector-replace.rs +++ b/tests/selector-replace.rs @@ -21,6 +21,11 @@ test!( "a {\n color: selector-replace(\":matches(c)\", \"c\", \"d\");\n}\n", "a {\n color: :matches(d);\n}\n" ); +test!( + psuedo_is, + "a {\n color: selector-replace(\":is(c)\", \"c\", \"d\");\n}\n", + "a {\n color: :is(d);\n}\n" +); test!( psuedo_not, "a {\n color: selector-replace(\":not(c)\", \"c\", \"d\");\n}\n", diff --git a/tests/selector-unify.rs b/tests/selector-unify.rs index 64eef91..a3185b9 100644 --- a/tests/selector-unify.rs +++ b/tests/selector-unify.rs @@ -668,3 +668,13 @@ test!( "a {\n color: selector-unify(\":matches(.c)\", \":matches(.d)\");\n}\n", "a {\n color: :matches(.c):matches(.d);\n}\n" ); +test!( + simple_pseudo_arg_is_same_selector_arg, + "a {\n color: selector-unify(\":is(.c)\", \":is(.c)\");\n}\n", + "a {\n color: :is(.c);\n}\n" +); +test!( + simple_pseudo_arg_is_different_selector_arg, + "a {\n color: selector-unify(\":is(.c)\", \":is(.d)\");\n}\n", + "a {\n color: :is(.c):is(.d);\n}\n" +); diff --git a/tests/selectors.rs b/tests/selectors.rs index afa5604..4b8717d 100644 --- a/tests/selectors.rs +++ b/tests/selectors.rs @@ -526,15 +526,21 @@ test!( "a:not(c) {\n x: y;\n}\n" ); test!( - psuedo_paren_removes_inner_placeholder, + psuedo_paren_removes_inner_placeholder_matches, "a:matches(%b, c) {x: y}", "a:matches(c) {\n x: y;\n}\n" ); test!( - matches_placeholder_removes_everything, + matches_placeholder_removes_everything_matches, "a:matches(%b) {x: y}", "" ); +test!( + psuedo_paren_removes_inner_placeholder_is, + "a:is(%b, c) {x: y}", + "a:is(c) {\n x: y;\n}\n" +); +test!(is_placeholder_removes_everything_is, "a:is(%b) {x: y}", ""); test!( touching_universal_stays_the_same, "a* {\n color: red;\n}\n",