Conversation
At the top level the parent reference list is [''], so substituting &\f with the empty parent inside a functional pseudo-class left a stray empty argument: :is(&, .c) compiled to :is(, .c), which is invalid CSS. Strip the now-empty argument together with its adjacent comma so the result is valid, matching the existing rule that a root & is removed. :is(&, .c) -> :is(.c) :is(.a, &, .b) -> :is(.a, .b) :is(&) -> :is()
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
At the top level (no parent rule), a
&inside a functional pseudo-class is substituted with an empty string, producing invalid CSS:css-treerejects the comma forms withSelector is expected:For comparison, the same input under a real parent already works, and a top-level
& .xalready compiles to a clean.x.Root cause
In
ruleset()the parent list at root is[''], sorule[x] === ''. The substitutionreplace(y, /&\f/g, rule[x])turns the&\fmarker into an empty string, so:is(&\f, .c)becomes:is(, .c).trim()only strips outer whitespace, so the empty argument and its comma stay inside the parentheses and the output is invalid.Fix
When the parent is empty (root), remove the
&\fmarker together with one adjacent comma instead of leaving an empty argument. The non-root substitution path is unchanged.This mirrors the existing rule that a root
&is removed (issue #333, and the "& root should be removed" test). The empty argument is dropped, so:All outputs parse cleanly with
css-tree. Empty:is()/:where()/:not()are valid (forgiving selector list) and are the closest valid result when the only argument was the absent parent.Tests
Added
& root inside functional pseudo should be removednext to the existing root-&tests. It usescompile/serializedirectly (no.userwrapper) so the empty-parent path is exercised.expected ':is(, .c){color:red;}' to equal ':is(.c){color:red;}'.