Skip to content
This repository has been archived by the owner on Feb 23, 2022. It is now read-only.

Allow ::slotted(selectors) #113

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 36 additions & 5 deletions src/com/google/common/css/compiler/ast/GssParserCC.jj
Original file line number Diff line number Diff line change
Expand Up @@ -711,6 +711,8 @@ PARSER_END(GssParserCC)
// Special handling needed because ':not' takes simple selectors as
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we just generalize this to two tokens: SIMPLE_SELECTOR_FUNCTION and SELECTOR_FUNCTION? It seems like a bunch of duplicate code in the pseudo expansion would go away.

Copy link
Author

@JamesXNelson JamesXNelson Mar 8, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aye. I agree that the duplication here is less than stellar.

However, I think the semantics of :not is slightly different.

:not() takes only a simple selector; one tag name, class name or id. I tested this in browser console, and it did not like any compound selectors ( :not(elementName.className) did not work)

The other three, ::slotted, :host and :host-context all support a compound selector (what simpleSelector() actually matches). ::slotted(div.clazz) is valid here.

I think simpleSelector should be renamed to compoundSelector, and then a new simpleSelector:

 elementName()
 | id()
 | className()
 | pseudo()

I will test tonight that :host-context does not also support combinators.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not supports compounding only through duplication:

div:not(.class1):not(.class2)

// an argument.
| < NOTFUNCTION: "not" <LEFTROUND> >
| < HOSTFUNCTION: "host" ("-context")? <LEFTROUND> >
| < SLOTTEDFUNCTION: ":slotted" <LEFTROUND> >
| < LANGFUNCTION: "lang" <LEFTROUND> >

// "calc("
Expand Down Expand Up @@ -902,8 +904,15 @@ CssRefinerNode id() :
}

// pseudo
// : ':' [ IDENT | [ ':' IDENT ] | [ 'not(' S* simple_selector S* ')' ]
// | [ 'lang(' S* IDENT S* ')' ] | [ FUNCTION S* nth S* ')' ] ]?
// : ':' [ IDENT
// | [ ':' IDENT ]
// | [ 'not(' S* simple_selector S* ')' ]
// | [ 'lang(' S* IDENT S* ')' ]
// | [ FUNCTION S* nth S* ')' ]
// | [ ':slotted(' S* simple_selector S* ')' ]
// | [ ':host(' S* selector S* ')' ]
// | [ ':host-context(' S* selector S* ')' ]
// ]?
// ;
CssRefinerNode pseudo() :
{
Expand All @@ -913,11 +922,22 @@ CssRefinerNode pseudo() :
String pseudo = null;
String argument = null;
List<Token> tokens = Lists.newArrayList();
CssSelectorNode notSelector = null;
CssSelectorNode innerSelector = null;
}
{
t = <COLON> { beginLocation = this.getLocation(); tokens.add(t); }
( ( t = <IDENTIFIER> { pseudo = t.image; tokens.add(t); } )
|
( // ::slotted( simple_selector )
t = <SLOTTEDFUNCTION> ( <S> )* { beginLocation = this.getLocation();
pseudo = t.image; tokens.add(t); }
innerSelector = simpleSelector()
( <S> )*
t = <RIGHTROUND> { tokens.add(t);
endLocation = this.getLocation();
return nodeBuilder.buildPseudoClassNode(pseudo, innerSelector,
this.mergeLocations(beginLocation, endLocation), tokens); }
)
|
( // ::identifier (pseudo-element)
t = <COLON> { tokens.add(t); }
Expand All @@ -930,11 +950,22 @@ CssRefinerNode pseudo() :
( // :not( simple_selector )
t = <NOTFUNCTION> ( <S> )* { beginLocation = this.getLocation();
pseudo = t.image; tokens.add(t); }
notSelector = simpleSelector()
innerSelector = simpleSelector()
( <S> )*
t = <RIGHTROUND> { tokens.add(t);
endLocation = this.getLocation();
return nodeBuilder.buildPseudoClassNode(pseudo, innerSelector,
this.mergeLocations(beginLocation, endLocation), tokens); }
)
|
( // :host( complex > selector ) or :host-context( complex > selector )
t = <HOSTFUNCTION> ( <S> )* { beginLocation = this.getLocation();
pseudo = t.image; tokens.add(t); }
innerSelector = selector()
( <S> )*
t = <RIGHTROUND> { tokens.add(t);
endLocation = this.getLocation();
return nodeBuilder.buildPseudoClassNode(pseudo, notSelector,
return nodeBuilder.buildPseudoClassNode(pseudo, innerSelector,
this.mergeLocations(beginLocation, endLocation), tokens); }
)
|
Expand Down