diff --git a/spec/core_functions/selector/extend/README.md b/spec/core_functions/selector/extend/README.md new file mode 100644 index 0000000000..1ea4c5c5ee --- /dev/null +++ b/spec/core_functions/selector/extend/README.md @@ -0,0 +1,7 @@ +Much of the complexity in the algorithm for extend comes from determining which +selectors are superselectors of which others and unifying two selectors, which +are covered more explicitly by specs for the `is-superselector()` and +`selector-unify()` functions, respectively. To avoid unnecessary duplication, +the specs for `selector-extend()` itself don't thoroughly exercise the +superselector or unification logic, and instead focuses on behavior that's +specific to the full extension process. diff --git a/spec/core_functions/selector/extend/complex.hrx b/spec/core_functions/selector/extend/complex.hrx new file mode 100644 index 0000000000..84e70d1687 --- /dev/null +++ b/spec/core_functions/selector/extend/complex.hrx @@ -0,0 +1,87 @@ +<===> parent/without_grandparent/simple/input.scss +a {b: selector-extend(".c .d", ".c", ".e")} + +<===> parent/without_grandparent/simple/output.css +a { + b: .c .d, .e .d; +} + +<===> +================================================================================ +<===> parent/without_grandparent/complex/input.scss +a {b: selector-extend(".c .d", ".c", ".e .f")} + +<===> parent/without_grandparent/complex/output.css +a { + b: .c .d, .e .f .d; +} + +<===> +================================================================================ +<===> parent/without_grandparent/list/input.scss +a {b: selector-extend(".c .d", ".c", ".e, .f")} + +<===> parent/without_grandparent/list/output.css +a { + b: .c .d, .e .d, .f .d; +} + +<===> +================================================================================ +<===> parent/with_grandparent/simple/input.scss +a {b: selector-extend(".c .d .e", ".d", ".f")} + +<===> parent/with_grandparent/simple/output.css +a { + b: .c .d .e, .c .f .e; +} + +<===> +================================================================================ +<===> parent/with_grandparent/complex/input.scss +a {b: selector-extend(".c .d .e", ".d", ".f .g")} + +<===> parent/with_grandparent/complex/output.css +a { + b: .c .d .e, .c .f .g .e, .f .c .g .e; +} + +<===> +================================================================================ +<===> parent/with_grandparent/list/input.scss +a {b: selector-extend(".c .d .e", ".d", ".f, .g")} + +<===> parent/with_grandparent/list/output.css +a { + b: .c .d .e, .c .f .e, .c .g .e; +} + +<===> +================================================================================ +<===> trailing_combinator/child/input.scss +a {b: selector-extend(".c .d", ".c", ".e >")} + +<===> trailing_combinator/child/output.css +a { + b: .c .d, .e > .d; +} + +<===> +================================================================================ +<===> trailing_combinator/sibling/input.scss +a {b: selector-extend(".c .d", ".c", ".e ~")} + +<===> trailing_combinator/sibling/output.css +a { + b: .c .d, .e ~ .d; +} + +<===> +================================================================================ +<===> trailing_combinator/next_sibling/input.scss +a {b: selector-extend(".c .d", ".c", ".e +")} + +<===> trailing_combinator/next_sibling/output.css +a { + b: .c .d, .e + .d; +} diff --git a/spec/core_functions/selector/extend/error.hrx b/spec/core_functions/selector/extend/error.hrx new file mode 100644 index 0000000000..1c73e1b005 --- /dev/null +++ b/spec/core_functions/selector/extend/error.hrx @@ -0,0 +1,291 @@ +<===> selector/parent/input.scss +a {b: selector-extend("&", "c", "d")} + +<===> selector/parent/error +Error: $selector: Parent selectors aren't allowed here. + , +1 | & + | ^ + ' + - 1:1 root stylesheet + , +1 | a {b: selector-extend("&", "c", "d")} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ' + input.scss 1:7 root stylesheet + +<===> selector/parent/error-libsass +Error: Parent selectors aren't allowed here. + on line 1:23 of input.scss, in function `selector-extend` + from line 1:7 of input.scss +>> a {b: selector-extend("&", "c", "d")} + + ----------------------^ + +<===> +================================================================================ +<===> selector/invalid/input.scss +a {b: selector-extend("[c", "d", "e")} + +<===> selector/invalid/error +Error: $selector: expected more input. + , +1 | [c + | ^ + ' + - 1:3 root stylesheet + , +1 | a {b: selector-extend("[c", "d", "e")} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ' + input.scss 1:7 root stylesheet + +<===> selector/invalid/error-libsass +Error: invalid operator in attribute selector for c + on line 1:24 of input.scss, in function `selector-extend` + from line 1:7 of input.scss +>> a {b: selector-extend("[c", "d", "e")} + + -----------------------^ + +<===> +================================================================================ +<===> selector/type/options.yml +--- +:todo: +- sass/libsass#2964 + +<===> selector/type/input.scss +a {b: selector-extend(1, "c", "d")} + +<===> selector/type/error +Error: $selector: 1 is not a valid selector: it must be a string, +a list of strings, or a list of lists of strings. + , +1 | a {b: selector-extend(1, "c", "d")} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ' + input.scss 1:7 root stylesheet + +<===> +================================================================================ +<===> extendee/parent/input.scss +a {b: selector-extend("c", "&", "d")} + +<===> extendee/parent/error +Error: $extendee: Parent selectors aren't allowed here. + , +1 | & + | ^ + ' + - 1:1 root stylesheet + , +1 | a {b: selector-extend("c", "&", "d")} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ' + input.scss 1:7 root stylesheet + +<===> extendee/parent/error-libsass +Error: Parent selectors aren't allowed here. + on line 1:28 of input.scss, in function `selector-extend` + from line 1:7 of input.scss +>> a {b: selector-extend("c", "&", "d")} + + ---------------------------^ + +<===> +================================================================================ +<===> extendee/complex/options.yml +--- +:todo: +- sass/libsass#3066 + +<===> +================================================================================ +<===> extendee/complex/string/input.scss +a {b: selector-extend("c", "d e", "f")} + +<===> extendee/complex/string/error +Error: Can't extend complex selector d e. + , +1 | a {b: selector-extend("c", "d e", "f")} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ' + input.scss 1:7 root stylesheet + +<===> +================================================================================ +<===> extendee/complex/list/input.scss +a {b: selector-extend("c", d e, "f")} + +<===> extendee/complex/list/error +Error: Can't extend complex selector d e. + , +1 | a {b: selector-extend("c", d e, "f")} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ' + input.scss 1:7 root stylesheet + +<===> +================================================================================ +<===> extendee/invalid/input.scss +a {b: selector-extend("c", "[d", "e")} + +<===> extendee/invalid/error +Error: $extendee: expected more input. + , +1 | [d + | ^ + ' + - 1:3 root stylesheet + , +1 | a {b: selector-extend("c", "[d", "e")} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ' + input.scss 1:7 root stylesheet + +<===> extendee/invalid/error-libsass +Error: invalid operator in attribute selector for d + on line 1:29 of input.scss, in function `selector-extend` + from line 1:7 of input.scss +>> a {b: selector-extend("c", "[d", "e")} + + ----------------------------^ + +<===> +================================================================================ +<===> extendee/type/options.yml +--- +:todo: +- sass/libsass#2964 + +<===> extendee/type/input.scss +a {b: selector-extend("c", 1, "d")} + +<===> extendee/type/error +Error: $extendee: 1 is not a valid selector: it must be a string, +a list of strings, or a list of lists of strings. + , +1 | a {b: selector-extend("c", 1, "d")} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ' + input.scss 1:7 root stylesheet + +<===> +================================================================================ +<===> extender/parent/input.scss +a {b: selector-extend("c", "d", "&")} + +<===> extender/parent/error +Error: $extender: Parent selectors aren't allowed here. + , +1 | & + | ^ + ' + - 1:1 root stylesheet + , +1 | a {b: selector-extend("c", "d", "&")} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ' + input.scss 1:7 root stylesheet + +<===> extender/parent/error-libsass +Error: Parent selectors aren't allowed here. + on line 1:33 of input.scss, in function `selector-extend` + from line 1:7 of input.scss +>> a {b: selector-extend("c", "d", "&")} + + --------------------------------^ + +<===> +================================================================================ +<===> extender/invalid/input.scss +a {b: selector-extend("c", "d", "[e")} + +<===> extender/invalid/error +Error: $extender: expected more input. + , +1 | [e + | ^ + ' + - 1:3 root stylesheet + , +1 | a {b: selector-extend("c", "d", "[e")} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ' + input.scss 1:7 root stylesheet + +<===> extender/invalid/error-libsass +Error: invalid operator in attribute selector for e + on line 1:34 of input.scss, in function `selector-extend` + from line 1:7 of input.scss +>> a {b: selector-extend("c", "d", "[e")} + + ---------------------------------^ + +<===> +================================================================================ +<===> extender/type/options.yml +--- +:todo: +- sass/libsass#2964 + +<===> extender/type/input.scss +a {b: selector-extend("c", "d", 1)} + +<===> extender/type/error +Error: $extender: 1 is not a valid selector: it must be a string, +a list of strings, or a list of lists of strings. + , +1 | a {b: selector-extend("c", "d", 1)} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ' + input.scss 1:7 root stylesheet + +<===> +================================================================================ +<===> too_many_args/input.scss +a {b: selector-extend("c", "d", "e", "f")} + +<===> too_many_args/error +Error: Only 3 arguments allowed, but 4 were passed. + ,--> input.scss +1 | a {b: selector-extend("c", "d", "e", "f")} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invocation + ' + ,--> sass:selector +1 | @function extend($selector, $extendee, $extender) { + | ======================================= declaration + ' + input.scss 1:7 root stylesheet + +<===> too_many_args/error-libsass +Error: wrong number of arguments (4 for 3) for `selector-extend' + on line 1:7 of input.scss +>> a {b: selector-extend("c", "d", "e", "f")} + + ------^ + +<===> +================================================================================ +<===> too_few_args/input.scss +a {b: selector-extend("c", "d")} + +<===> too_few_args/error +Error: Missing argument $extender. + ,--> input.scss +1 | a {b: selector-extend("c", "d")} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ invocation + ' + ,--> sass:selector +1 | @function extend($selector, $extendee, $extender) { + | ======================================= declaration + ' + input.scss 1:7 root stylesheet + +<===> too_few_args/error-libsass +Error: Function selector-extend is missing argument $extender. + on line 1 of input.scss +>> a {b: selector-extend("c", "d")} + + ------^ diff --git a/spec/core_functions/selector/extend/input.hrx b/spec/core_functions/selector/extend/input.hrx new file mode 100644 index 0000000000..99f38156e9 --- /dev/null +++ b/spec/core_functions/selector/extend/input.hrx @@ -0,0 +1,79 @@ +<===> non_string/README.md +These specs verify that all the arguments to `selector-extend()` can take the +generalized selector format. The full set of possible input formats is tested +with `selector-parse()`; this spec just verifies one example for each parameter. + +<===> +================================================================================ +<===> non_string/selector/input.scss +a {b: selector-extend((c, d c), "c", "e")} + +<===> non_string/selector/output.css +a { + b: c, e, d c; +} + +<===> +================================================================================ +<===> non_string/extendee/options.yml +--- +:todo: +- sass/libsass#3068 + +<===> non_string/extendee/input.scss +a {b: selector-extend("c.d", (c, ".d"), ".e")} + +<===> non_string/extendee/output.css +a { + b: c.d, .e; +} + +<===> +================================================================================ +<===> non_string/extender/input.scss +a {b: selector-extend("c", "c", (d, e f))} + +<===> non_string/extender/output.css +a { + b: c, d, e f; +} + +<===> +================================================================================ +<===> multiple_extendees/compound/input.scss +a {b: selector-extend("c.d", "c.d", ".e")} + +<===> multiple_extendees/compound/output.css +a { + b: c.d, .e; +} + +<===> +================================================================================ +<===> multiple_extendees/list/options.yml +--- +:todo: +- sass/libsass#3067 + +<===> multiple_extendees/list/input.scss +a {b: selector-extend("c.d", "c, .d", ".e")} + +<===> multiple_extendees/list/output.css +a { + b: c.d, .e; +} + +<===> +================================================================================ +<===> multiple_extendees/list_of_compound/options.yml +--- +:todo: +- sass/libsass#3067 + +<===> multiple_extendees/list_of_compound/input.scss +a {b: selector-extend("c.d.e.f", "c.d, .e.f", ".g")} + +<===> multiple_extendees/list_of_compound/output.css +a { + b: c.d.e.f, .g; +} diff --git a/spec/core_functions/selector/extend/no_op.hrx b/spec/core_functions/selector/extend/no_op.hrx new file mode 100644 index 0000000000..f77b5a7e09 --- /dev/null +++ b/spec/core_functions/selector/extend/no_op.hrx @@ -0,0 +1,227 @@ +<===> missing/input.scss +a {b: selector-extend("c", "d", "e")} + +<===> missing/output.css +a { + b: c; +} + +<===> +================================================================================ +<===> conflict/element/alone/input.scss +a {b: selector-extend("c.d", ".d", "e")} + +<===> conflict/element/alone/output.css +a { + b: c.d; +} + +<===> +================================================================================ +<===> conflict/element/with_class/input.scss +a {b: selector-extend("c.d", ".d", "e.f")} + +<===> conflict/element/with_class/output.css +a { + b: c.d; +} + +<===> +================================================================================ +<===> conflict/id/input.scss +a {b: selector-extend("#c.d", ".d", "#e")} + +<===> conflict/id/output.css +a { + b: #c.d; +} + +<===> +================================================================================ +<===> conflict/pseudo_element/unknown/input.scss +a {b: selector-extend("::c.d", ".d", "::e")} + +<===> conflict/pseudo_element/unknown/output.css +a { + b: ::c.d; +} + +<===> +================================================================================ +<===> conflict/pseudo_element/class_syntax/input.scss +a {b: selector-extend(":before.c", ".c", ":after")} + +<===> conflict/pseudo_element/class_syntax/output.css +a { + b: :before.c; +} + +<===> +================================================================================ +<===> conflict/universal/namespace_and_namespace/input.scss +a {b: selector-extend("c|*.d", ".d", "e|*")} + +<===> conflict/universal/namespace_and_namespace/output.css +a { + b: c|*.d; +} + +<===> +================================================================================ +<===> conflict/universal/namespace_and_empty/input.scss +a {b: selector-extend("c|*.d", ".d", "|*")} + +<===> conflict/universal/namespace_and_empty/output.css +a { + b: c|*.d; +} + +<===> +================================================================================ +<===> conflict/universal/empty_and_namespace/input.scss +a {b: selector-extend("|*.c", ".c", "d|*")} + +<===> conflict/universal/empty_and_namespace/output.css +a { + b: |*.c; +} + +<===> +================================================================================ +<===> conflict/universal/namespace_and_default/input.scss +a {b: selector-extend("c|*.d", ".d", "*")} + +<===> conflict/universal/namespace_and_default/output.css +a { + b: c|*.d; +} + +<===> +================================================================================ +<===> conflict/universal/default_and_namespace/input.scss +a {b: selector-extend("*.c", ".c", "d|*")} + +<===> conflict/universal/default_and_namespace/output.css +a { + b: *.c; +} + +<===> +================================================================================ +<===> conflict/universal/empty_and_default/input.scss +a {b: selector-extend("|*.c", ".c", "*")} + +<===> conflict/universal/empty_and_default/output.css +a { + b: |*.c; +} + +<===> +================================================================================ +<===> conflict/universal/default_and_empty/input.scss +a {b: selector-extend("*.c", ".c", "|*")} + +<===> conflict/universal/default_and_empty/output.css +a { + b: *.c; +} + +<===> +================================================================================ +<===> conflict/parent/input.scss +a {b: selector-extend("c > .d", ".d", "e > .f")} + +<===> conflict/parent/output.css +a { + b: c > .d; +} + +<===> +================================================================================ +<===> conflict/next_sibling/input.scss +a {b: selector-extend("c + .d", ".d", "e + .f")} + +<===> conflict/next_sibling/output.css +a { + b: c + .d; +} + +<===> +================================================================================ +<===> unification/identical_to_extendee/input.scss +a {b: selector-extend("c.d", ".d", ".d")} + +<===> unification/identical_to_extendee/output.css +a { + b: c.d; +} + +<===> +================================================================================ +<===> unification/identical_to_selector/input.scss +a {b: selector-extend("c.d", ".d", "c.d")} + +<===> unification/identical_to_selector/output.css +a { + b: c.d; +} + +<===> +================================================================================ +<===> unification/additional/simple/input.scss +a {b: selector-extend("c", "c", "c.d")} + +<===> unification/additional/simple/output.css +a { + b: c; +} + +<===> +================================================================================ +<===> unification/additional/ancestor/input.scss +a {b: selector-extend("c", "c", "d c")} + +<===> unification/additional/ancestor/output.css +a { + b: c; +} + +<===> +================================================================================ +<===> unification/additional/parent/input.scss +a {b: selector-extend("c", "c", "d > c")} + +<===> unification/additional/parent/output.css +a { + b: c; +} + +<===> +================================================================================ +<===> unification/additional/sibling/input.scss +a {b: selector-extend("c", "c", "d ~ c")} + +<===> unification/additional/sibling/output.css +a { + b: c; +} + +<===> +================================================================================ +<===> unification/additional/next_sibling/input.scss +a {b: selector-extend("c", "c", "d + c")} + +<===> unification/additional/next_sibling/output.css +a { + b: c; +} + +<===> +================================================================================ +<===> unification/subselector_of_target/input.scss +a {b: selector-extend(".c:matches(d)", ":matches(d)", "d.e")} + +<===> unification/subselector_of_target/output.css +a { + b: .c:matches(d); +} diff --git a/spec/core_functions/selector/extend/simple/README.md b/spec/core_functions/selector/extend/simple/README.md new file mode 100644 index 0000000000..90a8e3d730 --- /dev/null +++ b/spec/core_functions/selector/extend/simple/README.md @@ -0,0 +1 @@ +"Simple" as in "simple selectors", not as in "simple test cases". diff --git a/spec/core_functions/selector/extend/simple/attribute.hrx b/spec/core_functions/selector/extend/simple/attribute.hrx new file mode 100644 index 0000000000..e03c9efea0 --- /dev/null +++ b/spec/core_functions/selector/extend/simple/attribute.hrx @@ -0,0 +1,37 @@ +<===> equal/input.scss +a {b: selector-extend("[c=d]", "[c=d]", "e")} + +<===> equal/output.css +a { + b: [c=d], e; +} + +<===> +================================================================================ +<===> unequal/name/input.scss +a {b: selector-extend("[c=d]", "[e=d]", "f")} + +<===> unequal/name/output.css +a { + b: [c=d]; +} + +<===> +================================================================================ +<===> unequal/value/input.scss +a {b: selector-extend("[c=d]", "[c=e]", "f")} + +<===> unequal/value/output.css +a { + b: [c=d]; +} + +<===> +================================================================================ +<===> unequal/operator/input.scss +a {b: selector-extend("[c=d]", "[c^=d]", "f")} + +<===> unequal/operator/output.css +a { + b: [c=d]; +} diff --git a/spec/core_functions/selector/extend/simple/class.hrx b/spec/core_functions/selector/extend/simple/class.hrx new file mode 100644 index 0000000000..8faececf46 --- /dev/null +++ b/spec/core_functions/selector/extend/simple/class.hrx @@ -0,0 +1,17 @@ +<===> equal/input.scss +a {b: selector-extend(".c", ".c", "e")} + +<===> equal/output.css +a { + b: .c, e; +} + +<===> +================================================================================ +<===> unequal/input.scss +a {b: selector-extend(".c", ".d", "e")} + +<===> unequal/output.css +a { + b: .c; +} diff --git a/spec/core_functions/selector/extend/simple/id.hrx b/spec/core_functions/selector/extend/simple/id.hrx new file mode 100644 index 0000000000..9b6e533c41 --- /dev/null +++ b/spec/core_functions/selector/extend/simple/id.hrx @@ -0,0 +1,17 @@ +<===> equal/input.scss +a {b: selector-extend("#c", "#c", "e")} + +<===> equal/output.css +a { + b: #c, e; +} + +<===> +================================================================================ +<===> unequal/input.scss +a {b: selector-extend("#c", "#d", "e")} + +<===> unequal/output.css +a { + b: #c; +} diff --git a/spec/core_functions/selector/extend/simple/placeholder.hrx b/spec/core_functions/selector/extend/simple/placeholder.hrx new file mode 100644 index 0000000000..23f7749535 --- /dev/null +++ b/spec/core_functions/selector/extend/simple/placeholder.hrx @@ -0,0 +1,17 @@ +<===> equal/input.scss +a {b: selector-extend("%c", "%c", "e")} + +<===> equal/output.css +a { + b: %c, e; +} + +<===> +================================================================================ +<===> unequal/input.scss +a {b: selector-extend("%c", "%d", "e")} + +<===> unequal/output.css +a { + b: %c; +} diff --git a/spec/core_functions/selector/extend/simple/pseudo/arg.hrx b/spec/core_functions/selector/extend/simple/pseudo/arg.hrx new file mode 100644 index 0000000000..c1fb18f57c --- /dev/null +++ b/spec/core_functions/selector/extend/simple/pseudo/arg.hrx @@ -0,0 +1,84 @@ +<===> options.yml +--- +:todo: +- sass/libsass#3068 + +<===> +================================================================================ +<===> class/equal/input.scss +a {b: selector-extend(":c(@#$)", ":c(@#$)", "e")} + +<===> class/equal/output.css +a { + b: :c(@#$), e; +} + +<===> +================================================================================ +<===> class/unequal/name/input.scss +a {b: selector-extend(":c(@#$)", ":d(@#$)", "e")} + +<===> class/unequal/name/output.css +a { + b: :c(@#$); +} + +<===> +================================================================================ +<===> class/unequal/argument/input.scss +a {b: selector-extend(":c(@#$)", ":c(*&^)", "e")} + +<===> class/unequal/argument/output.css +a { + b: :c(@#$); +} + +<===> +================================================================================ +<===> class/unequal/has_argument/input.scss +a {b: selector-extend(":c(@#$)", ":c", "e")} + +<===> class/unequal/has_argument/output.css +a { + b: :c(@#$); +} + +<===> +================================================================================ +<===> element/equal/input.scss +a {b: selector-extend("::c(@#$)", "::c(@#$)", "e")} + +<===> element/equal/output.css +a { + b: ::c(@#$), e; +} + +<===> +================================================================================ +<===> element/unequal/name/input.scss +a {b: selector-extend("::c(@#$)", ":d(@#$)", "e")} + +<===> element/unequal/name/output.css +a { + b: ::c(@#$); +} + +<===> +================================================================================ +<===> element/unequal/argument/input.scss +a {b: selector-extend("::c(@#$)", "::c(*&^)", "e")} + +<===> element/unequal/argument/output.css +a { + b: ::c(@#$); +} + +<===> +================================================================================ +<===> element/unequal/has_argument/input.scss +a {b: selector-extend("::c(@#$)", "::c", "e")} + +<===> element/unequal/has_argument/output.css +a { + b: ::c(@#$); +} diff --git a/spec/core_functions/selector/extend/simple/pseudo/no_arg.hrx b/spec/core_functions/selector/extend/simple/pseudo/no_arg.hrx new file mode 100644 index 0000000000..68fc1b5ac1 --- /dev/null +++ b/spec/core_functions/selector/extend/simple/pseudo/no_arg.hrx @@ -0,0 +1,57 @@ +<===> class/equal/input.scss +a {b: selector-extend(":c", ":c", "e")} + +<===> class/equal/output.css +a { + b: :c, e; +} + +<===> +================================================================================ +<===> class/unequal/input.scss +a {b: selector-extend(":c", ":d", "e")} + +<===> class/unequal/output.css +a { + b: :c; +} + +<===> +================================================================================ +<===> class/and_element/input.scss +a {b: selector-extend(":c", "::c", "e")} + +<===> class/and_element/output.css +a { + b: :c; +} + +<===> +================================================================================ +<===> element/equal/input.scss +a {b: selector-extend("::c", "::c", "e")} + +<===> element/equal/output.css +a { + b: ::c, e; +} + +<===> +================================================================================ +<===> element/unequal/input.scss +a {b: selector-extend("::c", "::d", "e")} + +<===> element/unequal/output.css +a { + b: ::c; +} + +<===> +================================================================================ +<===> element/and_class/input.scss +a {b: selector-extend("::c", ":c", "e")} + +<===> element/and_class/output.css +a { + b: ::c; +} diff --git a/spec/core_functions/selector/extend/simple/pseudo/selector/idempotent.hrx b/spec/core_functions/selector/extend/simple/pseudo/selector/idempotent.hrx new file mode 100644 index 0000000000..49a74818f2 --- /dev/null +++ b/spec/core_functions/selector/extend/simple/pseudo/selector/idempotent.hrx @@ -0,0 +1,384 @@ +<===> README.md +Nesting one of these selector pseudoclasses within an identical selector +pseudoclass has no additional effect. As such, Sass flattens these nestings when +`@extend` would otherwise cause them to occur. + +<===> +================================================================================ +<===> not/README.md +Unlike other pseudo-selectors, when extending into `:not()` we add additional +`:not()`s to the compound selector, rather than adding selectors within the +original `:not()`. We're able to do this because (uniquely among selector +pseudos) `:not(X, Y)` is equivalent to `:not(X):not(Y)`. We *want* to do this +because older browsers only support a compound selector within `:not()` rather +than a selector list. + +<===> +================================================================================ +<===> not/simple/input.scss +a {b: selector-extend(":not(.c)", ".c", ".d")} + +<===> not/simple/output.css +a { + b: :not(.c):not(.d); +} + +<===> +================================================================================ +<===> not/list/input.scss +a {b: selector-extend(":not(.c)", ".c", ".d, .e")} + +<===> not/list/output.css +a { + b: :not(.c):not(.d):not(.e); +} + +<===> +================================================================================ +<===> not/complex/input.scss +a {b: selector-extend(":not(.c .d)", ".d", ".e .f")} + +<===> not/complex/output.css +a { + b: :not(.c .d):not(.c .e .f):not(.e .c .f); +} + +<===> +================================================================================ +<===> not/component/input.scss +a {b: selector-extend(":not(.c.d)", ".c", ".e")} + +<===> not/component/output.css +a { + b: :not(.c.d):not(.d.e); +} + +<===> +================================================================================ +<===> not/list_in_not/input.scss +// If the original :not() already contains a selector list, we add new selectors +// to that list because there's no risk of breaking additional browsers. +a {b: selector-extend(":not(.c, .d)", ".c", ".e")} + +<===> not/list_in_not/output.css +a { + b: :not(.c, .e, .d); +} + +<===> +================================================================================ +<===> not/matches/list/input.scss +a {b: selector-extend(":not(.c)", ".c", ":matches(.d, .e)")} + +<===> not/matches/list/output.css +a { + b: :not(.c):not(.d):not(.e); +} + +<===> +================================================================================ +<===> not/matches/list_of_complex/input.scss +a {b: selector-extend(":not(.c)", ".c", ":matches(.d .e, .f .g)")} + +<===> not/matches/list_of_complex/output.css +a { + b: :not(.c):not(.d .e):not(.f .g); +} + +<===> +================================================================================ +<===> not/matches/in_compound/input.scss +a {b: selector-extend(":not(.c)", ".c", ".d:matches(.e, .f)")} + +<===> not/matches/in_compound/output.css +a { + b: :not(.c):not(.d:matches(.e, .f)); +} + +<===> +================================================================================ +<===> not/not_in_extender/input.scss +// Ideally, this should emit `.d, :not(.c)`, but that would be the only +// situation where extending a pseudo selector could produce a full-on selector +// list. For the sake of simplicity of the `@extend` algorithm, we just ignore +// nested `:not()`s instead. +a {b: selector-extend(":not(.c)", ".c", ":not(.d)")} + +<===> not/not_in_extender/output.css +a { + b: :not(.c); +} + +<===> +================================================================================ +<===> matches/simple/input.scss +a {b: selector-extend(":matches(.c)", ".c", ".d")} + +<===> matches/simple/output.css +a { + b: :matches(.c, .d); +} + +<===> +================================================================================ +<===> matches/list/input.scss +a {b: selector-extend(":matches(.c)", ".c", ".d, .e")} + +<===> matches/list/output.css +a { + b: :matches(.c, .d, .e); +} + +<===> +================================================================================ +<===> matches/matches_in_extender/options.yml +--- +:todo: +- sass/libsass#3069 + +<===> matches/matches_in_extender/input.scss +a {b: selector-extend(":matches(.c)", ".c", ":matches(.d, .e)")} + +<===> matches/matches_in_extender/output.css +a { + b: :matches(.c, .d, .e); +} + +<===> +================================================================================ +<===> any/simple/input.scss +a {b: selector-extend(":any(.c)", ".c", ".d")} + +<===> any/simple/output.css +a { + b: :any(.c, .d); +} + +<===> +================================================================================ +<===> any/list/input.scss +a {b: selector-extend(":any(.c)", ".c", ".d, .e")} + +<===> any/list/output.css +a { + b: :any(.c, .d, .e); +} + +<===> +================================================================================ +<===> any/any_in_extender/options.yml +--- +:todo: +- sass/libsass#3069 + +<===> any/any_in_extender/input.scss +a {b: selector-extend(":any(.c)", ".c", ":any(.d, .e)")} + +<===> any/any_in_extender/output.css +a { + b: :any(.c, .d, .e); +} + +<===> +================================================================================ +<===> current/simple/input.scss +a {b: selector-extend(":current(.c)", ".c", ".d")} + +<===> current/simple/output.css +a { + b: :current(.c, .d); +} + +<===> +================================================================================ +<===> current/list/input.scss +a {b: selector-extend(":current(.c)", ".c", ".d, .e")} + +<===> current/list/output.css +a { + b: :current(.c, .d, .e); +} + +<===> +================================================================================ +<===> current/current_in_extender/options.yml +--- +:todo: +- sass/libsass#3069 + +<===> current/current_in_extender/input.scss +a {b: selector-extend(":current(.c)", ".c", ":current(.d, .e)")} + +<===> current/current_in_extender/output.css +a { + b: :current(.c, .d, .e); +} + +<===> +================================================================================ +<===> nth_child/options.yml +--- +:todo: +- sass/libsass#2961 + +<===> +================================================================================ +<===> nth_child/simple/input.scss +a {b: selector-extend(":nth-child(2n + 1 of .c)", ".c", ".d")} + +<===> nth_child/simple/output.css +a { + b: :nth-child(2n+1 of .c, .d); +} + +<===> +================================================================================ +<===> nth_child/list/input.scss +a {b: selector-extend(":nth-child(2n + 1 of .c)", ".c", ".d, .e")} + +<===> nth_child/list/output.css +a { + b: :nth-child(2n+1 of .c, .d, .e); +} + +<===> +================================================================================ +<===> nth_child/same_arg_in_extender/input.scss +a { + b: selector-extend( + ":nth-child(2n + 1 of .c)", + ".c", + ":nth-child(2n + 1 of .d, .e)"); +} + +<===> nth_child/same_arg_in_extender/output.css +a { + b: :nth-child(2n+1 of .c, .d, .e); +} + +<===> +================================================================================ +<===> nth_child/different_arg_in_extender/input.scss +// This should produce `:nth-child(2n + 1 of .c, :nth-child(2n + 1 of .d, .e))`. +// See sass/sass#2828. +a { + b: selector-extend( + ":nth-child(2n + 1 of .c)", + ".c", + ":nth-child(2n + 2 of .d, .e)"); +} + +<===> nth_child/different_arg_in_extender/output.css +a { + b: :nth-child(2n+1 of .c); +} + +<===> +================================================================================ +<===> nth_last_child/options.yml +--- +:todo: +- sass/libsass#2961 + +<===> +================================================================================ +<===> nth_last_child/simple/input.scss +a {b: selector-extend(":nth-last-child(2n + 1 of .c)", ".c", ".d")} + +<===> nth_last_child/simple/output.css +a { + b: :nth-last-child(2n+1 of .c, .d); +} + +<===> +================================================================================ +<===> nth_last_child/list/input.scss +a {b: selector-extend(":nth-last-child(2n + 1 of .c)", ".c", ".d, .e")} + +<===> nth_last_child/list/output.css +a { + b: :nth-last-child(2n+1 of .c, .d, .e); +} + +<===> +================================================================================ +<===> nth_last_child/same_arg_in_extender/input.scss +a { + b: selector-extend( + ":nth-last-child(2n + 1 of .c)", + ".c", + ":nth-last-child(2n + 1 of .d, .e)"); +} + +<===> nth_last_child/same_arg_in_extender/output.css +a { + b: :nth-last-child(2n+1 of .c, .d, .e); +} + +<===> +================================================================================ +<===> nth_last_child/different_arg_in_extender/input.scss +// This should produce +// `:nth-last-child(2n + 1 of .c, :nth-last-child(2n + 1 of .d, .e))`. +// See sass/sass#2828. +a { + b: selector-extend( + ":nth-last-child(2n + 1 of .c)", + ".c", + ":nth-last-child(2n + 2 of .d, .e)"); +} + +<===> nth_last_child/different_arg_in_extender/output.css +a { + b: :nth-last-child(2n+1 of .c); +} + +<===> +================================================================================ +<===> prefixed/simple/input.scss +a {b: selector-extend(":-ms-matches(.c)", ".c", ".d")} + +<===> prefixed/simple/output.css +a { + b: :-ms-matches(.c, .d); +} + +<===> +================================================================================ +<===> prefixed/list/input.scss +a {b: selector-extend(":-ms-matches(.c)", ".c", ".d, .e")} + +<===> prefixed/list/output.css +a { + b: :-ms-matches(.c, .d, .e); +} + +<===> +================================================================================ +<===> prefixed/same_prefix_in_extender/options.yml +--- +:todo: +- sass/libsass#3069 + +<===> prefixed/same_prefix_in_extender/input.scss +a {b: selector-extend(":-ms-matches(.c)", ".c", ":-ms-matches(.d, .e)")} + +<===> prefixed/same_prefix_in_extender/output.css +a { + b: :-ms-matches(.c, .d, .e); +} + +<===> +================================================================================ +<===> prefixed/different_prefix_in_extender/input.scss +a {b: selector-extend(":-ms-matches(.c)", ".c", ":-moz-matches(.d, .e)")} + +<===> prefixed/different_prefix_in_extender/output.css +a { + b: :-ms-matches(.c); +} + +<===> prefixed/different_prefix_in_extender/output-libsass.css +a { + b: :-ms-matches(.c, :-moz-matches(.d, .e)); +} diff --git a/spec/core_functions/selector/extend/simple/pseudo/selector/match.hrx b/spec/core_functions/selector/extend/simple/pseudo/selector/match.hrx new file mode 100644 index 0000000000..9f5f8d31d1 --- /dev/null +++ b/spec/core_functions/selector/extend/simple/pseudo/selector/match.hrx @@ -0,0 +1,162 @@ +<===> README.md +Specs for which selectors with argument lists count as "the same" when +determining which simple selectors to extend. `selector-extend` doesn't care +about the semantics of particular pseudo selectors. All it looks at is whether +they're structurally equal. + +<===> +================================================================================ +<===> unprefixed/class/equal/input.scss +a {b: selector-extend(":matches(c d.e, f g)", ":matches(c d.e, f g)", "h")} + +<===> unprefixed/class/equal/output.css +a { + b: :matches(c d.e, f g), h; +} + +<===> +================================================================================ +<===> unprefixed/class/unequal/name/input.scss +a {b: selector-extend(":matches(c d.e, f g)", ":-pfx-matches(c d.e, f g)", "h")} + +<===> unprefixed/class/unequal/name/output.css +a { + b: :matches(c d.e, f g); +} + +<===> +================================================================================ +<===> unprefixed/class/unequal/argument/input.scss +a {b: selector-extend(":matches(c d.e, f g)", ":matches(d, g)", "h")} + +<===> unprefixed/class/unequal/argument/output.css +a { + b: :matches(c d.e, f g); +} + +<===> +================================================================================ +<===> unprefixed/class/unequal/has_argument/input.scss +a {b: selector-extend(":matches(c d.e, f g)", ":matches", "h")} + +<===> unprefixed/class/unequal/has_argument/output.css +a { + b: :matches(c d.e, f g); +} + +<===> +================================================================================ +<===> unprefixed/element/equal/input.scss +a {b: selector-extend("::slotted(c.d, e.f)", "::slotted(c.d, e.f)", "g")} + +<===> unprefixed/element/equal/output.css +a { + b: ::slotted(c.d, e.f), g; +} + +<===> +================================================================================ +<===> unprefixed/element/unequal/name/input.scss +a {b: selector-extend("::slotted(c.d, e.f)", "::-pfx-slotted(c.d, e.f)", "g")} + +<===> unprefixed/element/unequal/name/output.css +a { + b: ::slotted(c.d, e.f); +} + +<===> +================================================================================ +<===> unprefixed/element/unequal/argument/input.scss +a {b: selector-extend("::slotted(c.d, e.f)", "::slotted(d, g)", "g")} + +<===> unprefixed/element/unequal/argument/output.css +a { + b: ::slotted(c.d, e.f); +} + +<===> +================================================================================ +<===> unprefixed/element/unequal/has_argument/input.scss +a {b: selector-extend("::slotted(c.d, e.f)", "::slotted", "g")} + +<===> unprefixed/element/unequal/has_argument/output.css +a { + b: ::slotted(c.d, e.f); +} + +<===> +================================================================================ +<===> prefixed/options.yml +--- +:todo: +- sass/libsass#2961 + +<===> +================================================================================ +<===> prefixed/equal/input.scss +a { + b: selector-extend( + ":nth-child(2n + 1 of c d.e, f g)", + ":nth-child(2n + 1 of c d.e, f g)", + "h"); +} + +<===> prefixed/equal/output.css +a { + b: :nth-child(2n+1 of c d.e, f g), h; +} + +<===> +================================================================================ +<===> prefixed/unequal/name/input.scss +a { + b: selector-extend( + ":nth-child(2n + 1 of c d.e, f g)", + ":nth-last-child(2n + 1 of c d.e, f g)", + "h"); +} + +<===> prefixed/unequal/name/output.css +a { + b: :nth-child(2n+1 of c d.e, f g); +} + +<===> +================================================================================ +<===> prefixed/unequal/argument/input.scss +a { + b: selector-extend( + ":nth-child(2n + 1 of c d.e, f g)", + ":nth-child(2n + 1 of d, g)", + "h"); +} + +<===> prefixed/unequal/argument/output.css +a { + b: :nth-child(2n+1 of c d.e, f g); +} + +<===> +================================================================================ +<===> prefixed/unequal/prefix/input.scss +a { + b: selector-extend( + ":nth-child(2n + 1 of c d.e, f g)", + ":nth-child(2n of c d.e, f g)", + "h"); +} + +<===> prefixed/unequal/prefix/output.css +a { + b: :nth-child(2n+1 of c d.e, f g); +} + +<===> +================================================================================ +<===> prefixed/unequal/has_argument/input.scss +a {b: selector-extend(":nth-child(2n + 1 of c d.e, f g)", ":nth-child", "h")} + +<===> prefixed/unequal/has_argument/output.css +a { + b: :nth-child(2n+1 of c d.e, f g); +} diff --git a/spec/core_functions/selector/extend/simple/pseudo/selector/non_idempotent.hrx b/spec/core_functions/selector/extend/simple/pseudo/selector/non_idempotent.hrx new file mode 100644 index 0000000000..9ccaf634db --- /dev/null +++ b/spec/core_functions/selector/extend/simple/pseudo/selector/non_idempotent.hrx @@ -0,0 +1,123 @@ +<===> README.md +Nesting one of these selector pseudoclasses within an identical selector +pseudoclass changes its semantics, so Sass never flattens these nestings. + +<===> +================================================================================ +<===> has/simple/input.scss +a {b: selector-extend(":has(.c)", ".c", ".d")} + +<===> has/simple/output.css +a { + b: :has(.c, .d); +} + +<===> +================================================================================ +<===> has/list/input.scss +a {b: selector-extend(":has(.c)", ".c", ".d, .e")} + +<===> has/list/output.css +a { + b: :has(.c, .d, .e); +} + +<===> +================================================================================ +<===> has/has_in_extender/input.scss +a {b: selector-extend(":has(.c)", ".c", ":has(.d)")} + +<===> has/has_in_extender/output.css +a { + b: :has(.c, :has(.d)); +} + +<===> +================================================================================ +<===> host/simple/input.scss +a {b: selector-extend(":host(.c)", ".c", ".d")} + +<===> host/simple/output.css +a { + b: :host(.c, .d); +} + +<===> +================================================================================ +<===> host/list/input.scss +a {b: selector-extend(":host(.c)", ".c", ".d, .e")} + +<===> host/list/output.css +a { + b: :host(.c, .d, .e); +} + +<===> +================================================================================ +<===> host/host_in_extender/input.scss +a {b: selector-extend(":host(.c)", ".c", ":host(.d)")} + +<===> host/host_in_extender/output.css +a { + b: :host(.c, :host(.d)); +} + +<===> +================================================================================ +<===> host_context/simple/input.scss +a {b: selector-extend(":host-context(.c)", ".c", ".d")} + +<===> host_context/simple/output.css +a { + b: :host-context(.c, .d); +} + +<===> +================================================================================ +<===> host_context/list/input.scss +a {b: selector-extend(":host-context(.c)", ".c", ".d, .e")} + +<===> host_context/list/output.css +a { + b: :host-context(.c, .d, .e); +} + +<===> +================================================================================ +<===> host_context/host_context_in_extender/input.scss +a {b: selector-extend(":host-context(.c)", ".c", ":host-context(.d)")} + +<===> host_context/host_context_in_extender/output.css +a { + b: :host-context(.c, :host-context(.d)); +} + +<===> +================================================================================ +<===> slotted/simple/input.scss +a {b: selector-extend("::slotted(.c)", ".c", ".d")} + +<===> slotted/simple/output.css +a { + b: ::slotted(.c, .d); +} + +<===> +================================================================================ +<===> slotted/list/input.scss +a {b: selector-extend("::slotted(.c)", ".c", ".d, .e")} + +<===> slotted/list/output.css +a { + b: ::slotted(.c, .d, .e); +} + +<===> +================================================================================ +<===> slotted/slotted_in_extender/input.scss +a {b: selector-extend("::slotted(.c)", ".c", "::slotted(.d)")} + +<===> slotted/slotted_in_extender/output.css +a { + b: ::slotted(.c, ::slotted(.d)); +} diff --git a/spec/core_functions/selector/extend/simple/type.hrx b/spec/core_functions/selector/extend/simple/type.hrx new file mode 100644 index 0000000000..2b25b6d7d5 --- /dev/null +++ b/spec/core_functions/selector/extend/simple/type.hrx @@ -0,0 +1,163 @@ +<===> equal/input.scss +a {b: selector-extend("c", "c", "e")} + +<===> equal/output.css +a { + b: c, e; +} + +<===> +================================================================================ +<===> unequal/input.scss +a {b: selector-extend("c", "d", "e")} + +<===> unequal/output.css +a { + b: c; +} + +<===> +================================================================================ +<===> and_universal/input.scss +a {b: selector-extend("c", "*", "d")} + +<===> and_universal/output.css +a { + b: c; +} + +<===> +================================================================================ +<===> namespace/explicit/and_explicit/equal/input.scss +a {b: selector-extend("c|d", "c|d", "e")} + +<===> namespace/explicit/and_explicit/equal/output.css +a { + b: c|d, e; +} + +<===> +================================================================================ +<===> namespace/explicit/and_explicit/unequal/input.scss +a {b: selector-extend("c|d", "e|d", "e")} + +<===> namespace/explicit/and_explicit/unequal/output.css +a { + b: c|d; +} + +<===> +================================================================================ +<===> namespace/explicit/and_implicit/input.scss +a {b: selector-extend("c|d", "d", "e")} + +<===> namespace/explicit/and_implicit/output.css +a { + b: c|d; +} + +<===> +================================================================================ +<===> namespace/explicit/and_empty/input.scss +a {b: selector-extend("c|d", "|d", "e")} + +<===> namespace/explicit/and_empty/output.css +a { + b: c|d; +} + +<===> +================================================================================ +<===> namespace/explicit/and_universal/input.scss +a {b: selector-extend("c|d", "*|d", "e")} + +<===> namespace/explicit/and_universal/output.css +a { + b: c|d; +} + +<===> +================================================================================ +<===> namespace/empty/and_explicit/input.scss +a {b: selector-extend("|c", "d|c", "e")} + +<===> namespace/empty/and_explicit/output.css +a { + b: |c; +} + +<===> +================================================================================ +<===> namespace/empty/and_implicit/input.scss +a {b: selector-extend("|c", "c", "d")} + +<===> namespace/empty/and_implicit/output.css +a { + b: |c; +} + +<===> +================================================================================ +<===> namespace/empty/and_empty/input.scss +a {b: selector-extend("|c", "|c", "d")} + +<===> namespace/empty/and_empty/output.css +a { + b: |c, d; +} + +<===> +================================================================================ +<===> namespace/empty/and_universal/input.scss +a {b: selector-extend("|c", "*|c", "d")} + +<===> namespace/empty/and_universal/output.css +a { + b: |c; +} + +<===> +================================================================================ +<===> namespace/universal/README.md +Although many of these extendees are subselectors of the targets, they're not +matched because this phase only cares about full structural equality. + +<===> +================================================================================ +<===> namespace/universal/and_explicit/input.scss +a {b: selector-extend("*|c", "d|c", "d")} + +<===> namespace/universal/and_explicit/output.css +a { + b: *|c; +} + +<===> +================================================================================ +<===> namespace/universal/and_implicit/input.scss +a {b: selector-extend("*|c", "c", "d")} + +<===> namespace/universal/and_implicit/output.css +a { + b: *|c; +} + +<===> +================================================================================ +<===> namespace/universal/and_empty/input.scss +a {b: selector-extend("*|c", "|c", "d")} + +<===> namespace/universal/and_empty/output.css +a { + b: *|c; +} + +<===> +================================================================================ +<===> namespace/universal/and_universal/input.scss +a {b: selector-extend("*|c", "*|c", "d")} + +<===> namespace/universal/and_universal/output.css +a { + b: *|c, d; +} diff --git a/spec/core_functions/selector/extend/simple/universal.hrx b/spec/core_functions/selector/extend/simple/universal.hrx new file mode 100644 index 0000000000..a260cae8f3 --- /dev/null +++ b/spec/core_functions/selector/extend/simple/universal.hrx @@ -0,0 +1,293 @@ +<===> README.md +Although many of these extendees are subselectors of the targets, they're not +matched because this phase only cares about full structural equality. + +<===> +================================================================================ +<===> equal/input.scss +a {b: selector-extend("*", "*", "c")} + +<===> equal/output.css +a { + b: *, c; +} + +<===> +================================================================================ +<===> and_type/input.scss +a {b: selector-extend("*", "c", "d")} + +<===> and_type/output.css +a { + b: *; +} + +<===> +================================================================================ +<===> and_class/input.scss +a {b: selector-extend("*", ".c", "d")} + +<===> and_class/output.css +a { + b: *; +} + +<===> +================================================================================ +<===> namespace/explicit/and_type/explicit/equal/input.scss +a {b: selector-extend("c|*", "c|d", "e")} + +<===> namespace/explicit/and_type/explicit/equal/output.css +a { + b: c|*; +} + +<===> +================================================================================ +<===> namespace/explicit/and_type/explicit/unequal/input.scss +a {b: selector-extend("c|*", "e|d", "e")} + +<===> namespace/explicit/and_type/explicit/unequal/output.css +a { + b: c|*; +} + +<===> +================================================================================ +<===> namespace/explicit/and_type/implicit/input.scss +a {b: selector-extend("c|*", "d", "e")} + +<===> namespace/explicit/and_type/implicit/output.css +a { + b: c|*; +} + +<===> +================================================================================ +<===> namespace/explicit/and_type/empty/input.scss +a {b: selector-extend("c|*", "|d", "e")} + +<===> namespace/explicit/and_type/empty/output.css +a { + b: c|*; +} + +<===> +================================================================================ +<===> namespace/explicit/and_universal/explicit/equal/input.scss +a {b: selector-extend("c|*", "c|*", "e")} + +<===> namespace/explicit/and_universal/explicit/equal/output.css +a { + b: c|*, e; +} + +<===> +================================================================================ +<===> namespace/explicit/and_universal/explicit/unequal/input.scss +a {b: selector-extend("c|*", "d|*", "e")} + +<===> namespace/explicit/and_universal/explicit/unequal/output.css +a { + b: c|*; +} + +<===> +================================================================================ +<===> namespace/explicit/and_universal/implicit/input.scss +a {b: selector-extend("c|*", "*", "e")} + +<===> namespace/explicit/and_universal/implicit/output.css +a { + b: c|*; +} + +<===> +================================================================================ +<===> namespace/explicit/and_universal/empty/input.scss +a {b: selector-extend("c|*", "|*", "e")} + +<===> namespace/explicit/and_universal/empty/output.css +a { + b: c|*; +} + +<===> +================================================================================ +<===> namespace/explicit/and_universal/universal/input.scss +a {b: selector-extend("c|*", "*|*", "e")} + +<===> namespace/explicit/and_universal/universal/output.css +a { + b: c|*; +} + +<===> +================================================================================ +<===> namespace/explicit/and_class/input.scss +a {b: selector-extend("c|*", ".d", "e")} + +<===> namespace/explicit/and_class/output.css +a { + b: c|*; +} + +<===> +================================================================================ +<===> namespace/empty/and_type/explicit/input.scss +a {b: selector-extend("|*", "c|d", "e")} + +<===> namespace/empty/and_type/explicit/output.css +a { + b: |*; +} + +<===> +================================================================================ +<===> namespace/empty/and_type/implicit/input.scss +a {b: selector-extend("|*", "d", "e")} + +<===> namespace/empty/and_type/implicit/output.css +a { + b: |*; +} + +<===> +================================================================================ +<===> namespace/empty/and_type/empty/input.scss +a {b: selector-extend("|*", "|d", "e")} + +<===> namespace/empty/and_type/empty/output.css +a { + b: |*; +} + +<===> +================================================================================ +<===> namespace/empty/and_universal/explicit/input.scss +a {b: selector-extend("|*", "c|*", "d")} + +<===> namespace/empty/and_universal/explicit/output.css +a { + b: |*; +} + +<===> +================================================================================ +<===> namespace/empty/and_universal/implicit/input.scss +a {b: selector-extend("|*", "*", "c")} + +<===> namespace/empty/and_universal/implicit/output.css +a { + b: |*; +} + +<===> +================================================================================ +<===> namespace/empty/and_universal/empty/input.scss +a {b: selector-extend("|*", "|*", "c")} + +<===> namespace/empty/and_universal/empty/output.css +a { + b: |*, c; +} + +<===> +================================================================================ +<===> namespace/empty/and_universal/universal/input.scss +a {b: selector-extend("|*", "*|*", "c")} + +<===> namespace/empty/and_universal/universal/output.css +a { + b: |*; +} + +<===> +================================================================================ +<===> namespace/empty/and_class/input.scss +a {b: selector-extend("|*", ".c", "d")} + +<===> namespace/empty/and_class/output.css +a { + b: |*; +} + +<===> +================================================================================ +<===> namespace/universal/and_type/explicit/input.scss +a {b: selector-extend("*|*", "c|d", "e")} + +<===> namespace/universal/and_type/explicit/output.css +a { + b: *|*; +} + +<===> +================================================================================ +<===> namespace/universal/and_type/implicit/input.scss +a {b: selector-extend("*|*", "c", "d")} + +<===> namespace/universal/and_type/implicit/output.css +a { + b: *|*; +} + +<===> +================================================================================ +<===> namespace/universal/and_type/empty/input.scss +a {b: selector-extend("*|*", "|c", "d")} + +<===> namespace/universal/and_type/empty/output.css +a { + b: *|*; +} + +<===> +================================================================================ +<===> namespace/universal/and_universal/explicit/input.scss +a {b: selector-extend("*|*", "c|*", "d")} + +<===> namespace/universal/and_universal/explicit/output.css +a { + b: *|*; +} + +<===> +================================================================================ +<===> namespace/universal/and_universal/implicit/input.scss +a {b: selector-extend("*|*", "*", "c")} + +<===> namespace/universal/and_universal/implicit/output.css +a { + b: *|*; +} + +<===> +================================================================================ +<===> namespace/universal/and_universal/empty/input.scss +a {b: selector-extend("*|*", "|*", "c")} + +<===> namespace/universal/and_universal/empty/output.css +a { + b: *|*; +} + +<===> +================================================================================ +<===> namespace/universal/and_universal/universal/input.scss +a {b: selector-extend("*|*", "*|*", "c")} + +<===> namespace/universal/and_universal/universal/output.css +a { + b: *|*, c; +} + +<===> +================================================================================ +<===> namespace/universal/and_class/input.scss +a {b: selector-extend("*|*", ".c", "d")} + +<===> namespace/universal/and_class/output.css +a { + b: *|*; +}