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); }
( )*