diff --git a/src/NUglify.Tests/Css/Bugs.cs b/src/NUglify.Tests/Css/Bugs.cs
index cdedb7a5..9032fd02 100644
--- a/src/NUglify.Tests/Css/Bugs.cs
+++ b/src/NUglify.Tests/Css/Bugs.cs
@@ -133,6 +133,12 @@ public void Bug309()
public void Bug331()
{
TestHelper.Instance.RunTest();
+ }
+
+ [Test]
+ public void Bug412()
+ {
+ TestHelper.Instance.RunTest();
}
[Test]
diff --git a/src/NUglify.Tests/NUglify.Tests.csproj b/src/NUglify.Tests/NUglify.Tests.csproj
index b6be68a0..b39bc867 100644
--- a/src/NUglify.Tests/NUglify.Tests.csproj
+++ b/src/NUglify.Tests/NUglify.Tests.csproj
@@ -404,6 +404,9 @@
PreserveNewest
+
+ PreserveNewest
+
PreserveNewest
@@ -446,6 +449,9 @@
PreserveNewest
+
+ PreserveNewest
+
PreserveNewest
diff --git a/src/NUglify.Tests/TestData/CSS/Expected/Bugs/Bug412.css b/src/NUglify.Tests/TestData/CSS/Expected/Bugs/Bug412.css
new file mode 100644
index 00000000..1199ef97
--- /dev/null
+++ b/src/NUglify.Tests/TestData/CSS/Expected/Bugs/Bug412.css
@@ -0,0 +1 @@
+.foo:has(span span){color:#f00;text-align:center}
\ No newline at end of file
diff --git a/src/NUglify.Tests/TestData/CSS/Input/Bugs/Bug412.css b/src/NUglify.Tests/TestData/CSS/Input/Bugs/Bug412.css
new file mode 100644
index 00000000..13d1046c
--- /dev/null
+++ b/src/NUglify.Tests/TestData/CSS/Input/Bugs/Bug412.css
@@ -0,0 +1,4 @@
+.foo:has(span span) {
+ color: #f00;
+ text-align: center;
+}
diff --git a/src/NUglify/Css/CssParser.cs b/src/NUglify/Css/CssParser.cs
index e6338385..fb384009 100644
--- a/src/NUglify/Css/CssParser.cs
+++ b/src/NUglify/Css/CssParser.cs
@@ -2464,7 +2464,10 @@ Parsed ParsePseudo()
case TokenType.Not:
case TokenType.Any:
- case TokenType.Matches:
+ case TokenType.Matches:
+ case TokenType.Is:
+ case TokenType.Where:
+ case TokenType.Has:
AppendCurrent();
SkipSpace();
diff --git a/src/NUglify/Css/CssScanner.cs b/src/NUglify/Css/CssScanner.cs
index 0b3dabbc..13e6085f 100644
--- a/src/NUglify/Css/CssScanner.cs
+++ b/src/NUglify/Css/CssScanner.cs
@@ -1185,6 +1185,7 @@ CssToken ScanIdent()
NextChar();
var tokenType = TokenType.Function;
+ // TODO: Refactor to shared TokenType of "PsuedoWithNested"
if (ident.Equals("not", StringComparison.OrdinalIgnoreCase))
{
tokenType = TokenType.Not;
@@ -1197,6 +1198,18 @@ CssToken ScanIdent()
{
tokenType = TokenType.Matches;
}
+ else if (ident.Equals("has", StringComparison.OrdinalIgnoreCase))
+ {
+ tokenType = TokenType.Has;
+ }
+ else if (ident.Equals("is", StringComparison.OrdinalIgnoreCase))
+ {
+ tokenType = TokenType.Is;
+ }
+ else if (ident.Equals("where", StringComparison.OrdinalIgnoreCase))
+ {
+ tokenType = TokenType.Where;
+ }
token = new CssToken(tokenType, ident + '(', m_context);
}
diff --git a/src/NUglify/Css/CssToken.cs b/src/NUglify/Css/CssToken.cs
index 75e85ddb..e0f22900 100644
--- a/src/NUglify/Css/CssToken.cs
+++ b/src/NUglify/Css/CssToken.cs
@@ -179,6 +179,9 @@ enum TokenType
Function,
Not,
Any,
+ Has,
+ Is,
+ Where,
Matches,
UnicodeRange,
ProgId,