diff --git a/ph-css/src/main/java/com/helger/css/decl/CSSSelectorMemberHost.java b/ph-css/src/main/java/com/helger/css/decl/CSSSelectorMemberHost.java new file mode 100644 index 00000000..78ed46d3 --- /dev/null +++ b/ph-css/src/main/java/com/helger/css/decl/CSSSelectorMemberHost.java @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2014-2022 Philip Helger (www.helger.com) + * philip[at]helger[dot]com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.helger.css.decl; + +import javax.annotation.Nonnegative; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import javax.annotation.concurrent.NotThreadSafe; + +import com.helger.commons.ValueEnforcer; +import com.helger.commons.annotation.Nonempty; +import com.helger.commons.annotation.ReturnsMutableCopy; +import com.helger.commons.collection.impl.CommonsArrayList; +import com.helger.commons.collection.impl.ICommonsList; +import com.helger.commons.hashcode.HashCodeGenerator; +import com.helger.commons.state.EChange; +import com.helger.commons.string.ToStringGenerator; +import com.helger.css.CSSSourceLocation; +import com.helger.css.ECSSVersion; +import com.helger.css.ICSSSourceLocationAware; +import com.helger.css.ICSSVersionAware; +import com.helger.css.ICSSWriterSettings; + +/** + * Represents a single, simple CSS selector as used for the ":host()" CSS pseudo class function.
+ * Note: this class was completely redesigned for version 3.7.4 + * + * @author Philip Helger + */ +@NotThreadSafe +public class CSSSelectorMemberHost implements ICSSSelectorMember, ICSSVersionAware, ICSSSourceLocationAware +{ + private final ICSSSelectorMember m_aSimpleSelector; + private CSSSourceLocation m_aSourceLocation; + + public CSSSelectorMemberHost (@Nonnull final ICSSSelectorMember aSimpleSelector) + { + ValueEnforcer.notNull (aSimpleSelector, "SimpleSelector"); + m_aSimpleSelector = aSimpleSelector; + } + + @Nonnull + public ICSSSelectorMember getSimpleSelector () + { + return m_aSimpleSelector; + } + + @Nonnull + @Nonempty + public String getAsCSSString (@Nonnull final ICSSWriterSettings aSettings, @Nonnegative final int nIndentLevel) + { + aSettings.checkVersionRequirements (this); + + final StringBuilder aSB = new StringBuilder (":host("); + aSB.append (m_aSimpleSelector.getAsCSSString (aSettings, 0)); + return aSB.append (')').toString (); + } + + @Nonnull + public ECSSVersion getMinimumCSSVersion () + { + return ECSSVersion.CSS30; + } + + public void setSourceLocation (@Nullable final CSSSourceLocation aSourceLocation) + { + m_aSourceLocation = aSourceLocation; + } + + @Nullable + public CSSSourceLocation getSourceLocation () + { + return m_aSourceLocation; + } + + @Override + public boolean equals (final Object o) + { + if (o == this) + return true; + if (o == null || !getClass ().equals (o.getClass ())) + return false; + final CSSSelectorMemberHost rhs = (CSSSelectorMemberHost) o; + return m_aSimpleSelector.equals (rhs.m_aSimpleSelector); + } + + @Override + public int hashCode () + { + return new HashCodeGenerator (this).append (m_aSimpleSelector).getHashCode (); + } + + @Override + public String toString () + { + return new ToStringGenerator (null).append ("simpleSelector", m_aSimpleSelector) + .appendIfNotNull ("sourceLocation", m_aSourceLocation) + .getToString (); + } +} diff --git a/ph-css/src/main/java/com/helger/css/decl/CSSSelectorMemberSlotted.java b/ph-css/src/main/java/com/helger/css/decl/CSSSelectorMemberSlotted.java new file mode 100644 index 00000000..fa7f7734 --- /dev/null +++ b/ph-css/src/main/java/com/helger/css/decl/CSSSelectorMemberSlotted.java @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2014-2022 Philip Helger (www.helger.com) + * philip[at]helger[dot]com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.helger.css.decl; + +import javax.annotation.Nonnegative; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import javax.annotation.concurrent.NotThreadSafe; + +import com.helger.commons.ValueEnforcer; +import com.helger.commons.annotation.Nonempty; +import com.helger.commons.annotation.ReturnsMutableCopy; +import com.helger.commons.collection.impl.CommonsArrayList; +import com.helger.commons.collection.impl.ICommonsList; +import com.helger.commons.hashcode.HashCodeGenerator; +import com.helger.commons.state.EChange; +import com.helger.commons.string.ToStringGenerator; +import com.helger.css.CSSSourceLocation; +import com.helger.css.ECSSVersion; +import com.helger.css.ICSSSourceLocationAware; +import com.helger.css.ICSSVersionAware; +import com.helger.css.ICSSWriterSettings; + +/** + * Represents a single, simple CSS selector as used for the "::slotted()" CSS pseudo element.
+ * Note: this class was completely redesigned for version 3.7.4 + * + * @author Philip Helger + */ +@NotThreadSafe +public class CSSSelectorMemberSlotted implements ICSSSelectorMember, ICSSVersionAware, ICSSSourceLocationAware +{ + private final ICSSSelectorMember m_aSimpleSelector; + private CSSSourceLocation m_aSourceLocation; + + public CSSSelectorMemberSlotted (@Nonnull final ICSSSelectorMember aSimpleSelector) + { + ValueEnforcer.notNull (aSimpleSelector, "SimpleSelector"); + m_aSimpleSelector = aSimpleSelector; + } + + @Nonnull + public ICSSSelectorMember getSimpleSelector () + { + return m_aSimpleSelector; + } + + @Nonnull + @Nonempty + public String getAsCSSString (@Nonnull final ICSSWriterSettings aSettings, @Nonnegative final int nIndentLevel) + { + aSettings.checkVersionRequirements (this); + + final StringBuilder aSB = new StringBuilder ("::slotted("); + aSB.append (m_aSimpleSelector.getAsCSSString (aSettings, 0)); + return aSB.append (')').toString (); + } + + @Nonnull + public ECSSVersion getMinimumCSSVersion () + { + return ECSSVersion.CSS30; + } + + public void setSourceLocation (@Nullable final CSSSourceLocation aSourceLocation) + { + m_aSourceLocation = aSourceLocation; + } + + @Nullable + public CSSSourceLocation getSourceLocation () + { + return m_aSourceLocation; + } + + @Override + public boolean equals (final Object o) + { + if (o == this) + return true; + if (o == null || !getClass ().equals (o.getClass ())) + return false; + final CSSSelectorMemberSlotted rhs = (CSSSelectorMemberSlotted) o; + return m_aSimpleSelector.equals (rhs.m_aSimpleSelector); + } + + @Override + public int hashCode () + { + return new HashCodeGenerator (this).append (m_aSimpleSelector).getHashCode (); + } + + @Override + public String toString () + { + return new ToStringGenerator (null).append ("simpleSelector", m_aSimpleSelector) + .appendIfNotNull ("sourceLocation", m_aSourceLocation) + .getToString (); + } +} diff --git a/ph-css/src/main/java/com/helger/css/handler/CSSNodeToDomainObject.java b/ph-css/src/main/java/com/helger/css/handler/CSSNodeToDomainObject.java index b0e6562a..2b014500 100644 --- a/ph-css/src/main/java/com/helger/css/handler/CSSNodeToDomainObject.java +++ b/ph-css/src/main/java/com/helger/css/handler/CSSNodeToDomainObject.java @@ -267,6 +267,23 @@ private ICSSSelectorMember _createSelectorMember (final CSSNode aNode) return ret; } + if (ECSSNodeType.HOST.isNode(aChildNode, m_eVersion)) + { + final ICSSSelectorMember aMember = _createSelectorMember (aChildNode.jjtGetChild(0)); + final CSSSelectorMemberHost ret = new CSSSelectorMemberHost(aMember); + if (m_bUseSourceLocation) + ret.setSourceLocation (aNode.getSourceLocation ()); + return ret; + } + + if (ECSSNodeType.SLOTTED.isNode(aChildNode, m_eVersion)) { + final ICSSSelectorMember aMember = _createSelectorMember (aChildNode.jjtGetChild(0)); + final CSSSelectorMemberSlotted ret = new CSSSelectorMemberSlotted(aMember); + if (m_bUseSourceLocation) + ret.setSourceLocation (aNode.getSourceLocation ()); + return ret; + } + // It's a function (e.g. ":lang(fr)") final CSSExpression aExpr = _createExpression (aChildNode); final CSSSelectorMemberFunctionLike ret = new CSSSelectorMemberFunctionLike (aNode.getText (), aExpr); diff --git a/ph-css/src/main/java/com/helger/css/handler/ECSSNodeType.java b/ph-css/src/main/java/com/helger/css/handler/ECSSNodeType.java index 28626351..a3ed72f2 100644 --- a/ph-css/src/main/java/com/helger/css/handler/ECSSNodeType.java +++ b/ph-css/src/main/java/com/helger/css/handler/ECSSNodeType.java @@ -57,6 +57,8 @@ public enum ECSSNodeType HASH (ParserCSS30TreeConstants.JJTHASH), CLASS (ParserCSS30TreeConstants.JJTCLASS), PSEUDO (ParserCSS30TreeConstants.JJTPSEUDO), + HOST (ParserCSS30TreeConstants.JJTHOST), + SLOTTED (ParserCSS30TreeConstants.JJTSLOTTED), NEGATION (ParserCSS30TreeConstants.JJTNEGATION), ATTRIB (ParserCSS30TreeConstants.JJTATTRIB), ATTRIBOPERATOR (ParserCSS30TreeConstants.JJTATTRIBOPERATOR), diff --git a/ph-css/src/main/jjtree/ParserCSS30.jjt b/ph-css/src/main/jjtree/ParserCSS30.jjt index e398e826..50141a21 100644 --- a/ph-css/src/main/jjtree/ParserCSS30.jjt +++ b/ph-css/src/main/jjtree/ParserCSS30.jjt @@ -300,6 +300,8 @@ TOKEN : | < FUNCTION_CALC: "calc(" | "-" "-calc(" > | < FUNCTION_NOT: ":not(" > +| < FUNCTION_HOST: "host(" > +| < FUNCTION_SLOTTED: "slotted(" > | < FUNCTION_NTH: "nth-child(" | "nth-last-child(" | "nth-of-type(" @@ -765,9 +767,9 @@ void mathSum() #void : {} { mathProduct() ( LOOKAHEAD(2) - + ( )* mathSumOperator() - + ( )* mathProduct () )* } @@ -1006,6 +1008,18 @@ void pseudoNth () #nth : ( )* } +void pseudoHost () #host : {} +{ + ( )* + ( simpleSelectorSequence () )? +} + +void pseudoSlotted () #slotted : {} +{ + ( )* + ( simpleSelectorSequence () )? +} + void pseudo() : {} { { jjtThis.setText (":"); } @@ -1014,6 +1028,12 @@ void pseudo() : {} ( { jjtThis.appendText (token.image); } pseudoNth() // do not append because of expression! + | { jjtThis.appendText (token.image); } + pseudoHost() + // do not append because of expression! + | { jjtThis.appendText (token.image); } + pseudoSlotted() + // do not append because of expression! | LOOKAHEAD( ) { jjtThis.appendText (token.image); } ( )*