Fix specificity of Selectors Level 4 functional pseudo-classes#79
Open
gaoflow wants to merge 2 commits into
Open
Fix specificity of Selectors Level 4 functional pseudo-classes#79gaoflow wants to merge 2 commits into
gaoflow wants to merge 2 commits into
Conversation
The functional selector-list pseudo-classes :is(), :has(), :matches() and :any() were each counted as a single class and their arguments were not counted at all, so their specificity was always (0,0,1,0). Per the CSS Selectors specification they contribute the specificity of their argument instead, and :where() always contributes zero. Track the open selector-list pseudo-classes on a stack and, while inside one whose arguments count, fold their tokens into the specificity as usual; skip them inside any enclosing :where(). The function token itself no longer counts as a class.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Following #75 (parsing of the Level 4 functional pseudo-classes) and #76
(specificity of simple pseudo-classes), the functional selector-list
pseudo-classes are still scored incorrectly.
:is(),:has(),:matches()and
:any()were each counted as a single class, and the selector passed astheir argument was not counted at all — so their specificity was always
(0, 0, 1, 0)regardless of the argument.:where()was scored the same way.Per the CSS Selectors spec:
:is(),:has(),:matches(),:any()take the specificity of the mostspecific complex selector in their argument.
:where()always contributes zero.No test locked in the old values, so this is a latent scoring bug rather than
intended behavior.
Fix
Track the currently-open selector-list pseudo-classes on a stack. While inside
one whose arguments count toward specificity, fold its argument's tokens into
the running specificity as usual; a token is skipped if it is nested inside any
enclosing
:where()(which zeroes everything it contains, including a nested:is()). The functional pseudo token itself is no longer counted as a class.Tests
Extended
test_specificitywith the functional pseudo-classes and theirnesting, e.g.
:where(#a)→(0,0,0,0),:is(#a)→(0,1,0,0),:is(.x .y #z)→(0,1,2,0),:has(option:checked)→(0,0,1,1),div:is(.a):where(#b)→(0,0,1,1), and nested cases:is(:where(#a))/:where(:is(#a))→(0,0,0,0). Full suite: 396 passed, 43 xfailed.