diff --git a/CHANGELOG.md b/CHANGELOG.md index 97c6683a..97620c16 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,7 +27,7 @@ Please also have a look at our `getPropertyName()` (#1506) - `Selector` is now represented as a sequence of `Selector\Component` objects which can be accessed via `getComponents()`, manipulated individually, or set - via `setComponents()` (#1478, #1486, #1487, #1488, #1494, #1496, #1536) + via `setComponents()` (#1478, #1486, #1487, #1488, #1494, #1496, #1536, #1537) - `Selector::setSelector()` and `Selector` constructor will now throw exception upon provision of an invalid selectior (#1498, #1502) - Clean up extra whitespace in CSS selector (#1398) diff --git a/src/Property/Selector/CompoundSelector.php b/src/Property/Selector/CompoundSelector.php index 1e6fa541..80b1670c 100644 --- a/src/Property/Selector/CompoundSelector.php +++ b/src/Property/Selector/CompoundSelector.php @@ -48,7 +48,7 @@ class CompoundSelector implements Component (?: (?: # any sequence of valid unescaped characters, except quotes - [a-zA-Z0-9\\x{00A0}-\\x{FFFF}_^$|*~=\\[\\]()\\-\\.:#,\\s]++ + [a-zA-Z0-9\\x{00A0}-\\x{FFFF}_^$|*=~\\[\\]()\\-\\s\\.:#+>,]++ | # one or more escaped characters (?:\\\\.)++ diff --git a/tests/Unit/Property/Selector/CompoundSelectorTest.php b/tests/Unit/Property/Selector/CompoundSelectorTest.php index e8e659e8..b42c76f1 100644 --- a/tests/Unit/Property/Selector/CompoundSelectorTest.php +++ b/tests/Unit/Property/Selector/CompoundSelectorTest.php @@ -68,6 +68,16 @@ public static function provideCompoundSelectorAndSpecificity(): array 'attribute with case insensitive modifier' => ['a[href*="insensitive" i]', 12], // TODO, broken: specificity should be 21, but the calculator doesn't realize the `.` is in a string. 'multiple attributes' => ['a[href^="https://"][href$=".org"]', 31], + // TODO, broken: specificity should be 11, but the calculator is treating the `n` as a type selector. + 'nth-last-child' => ['li:nth-last-child(2n+3)', 12], + // TODO, maybe broken: specificity should probably be 2 (1 for `p` and 1 for `span`). + '`not` with descendent combinator' => [':not(p span)', 1], + // TODO, maybe broken: specificity should probably be 2 (1 for `p` and 1 for `span`). + '`not` with child combinator' => [':not(p > span)', 1], + // TODO, maybe broken: specificity should probably be 2 (1 for `h1` and 1 for `p`). + '`not` with next-sibling combinator' => [':not(h1 + p)', 1], + // TODO, maybe broken: specificity should probably be 2 (1 for `h1` and 1 for `p`). + '`not` with subsequent-sibling combinator' => [':not(h1 ~ p)', 1], ]; }