This is an automated email from the ASF dual-hosted git repository. joshtynjala pushed a commit to branch develop in repository https://gitbox.apache.org/repos/asf/royale-compiler.git
commit 1422cba7b228960bfa263cc5712b313f834a153a Author: Josh Tynjala <[email protected]> AuthorDate: Wed Oct 15 13:28:49 2025 -0700 CSS: support more CSS pseudo-classes with arguments Previously, we supported :not() only. Now, more functions are recognized. CSSSelectorCondition now includes optional arguments, which are null when there are no arguments, or a string when there are. ConditionType removes NOT and uses PSUEDO. --- .../driver/js/royale/JSCSSCompilationSession.java | 5 ++++ .../test/resources/royale/files/CSSTestSource.css | 4 ++++ .../royale/files/CSSTestSource_encoded_result.txt | 4 ++++ .../royale/files/CSSTestSource_result.css | 5 ++++ .../apache/royale/compiler/internal/css/CSSTree.g | 27 ++++++++++++++++++---- .../apache/royale/compiler/css/ConditionType.java | 7 +----- .../royale/compiler/css/ICSSSelectorCondition.java | 5 ++++ .../royale/compiler/internal/css/CSSSelector.java | 5 ++++ .../internal/css/CSSSelectorCondition.java | 24 ++++++++++++++++++- compiler/src/test/build.xml | 2 +- .../internal/css/CSSSelectorConditionTests.java | 22 ++++++++++++++++++ 11 files changed, 97 insertions(+), 13 deletions(-) diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/driver/js/royale/JSCSSCompilationSession.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/driver/js/royale/JSCSSCompilationSession.java index c93d81eda..611dd0c3a 100644 --- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/driver/js/royale/JSCSSCompilationSession.java +++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/driver/js/royale/JSCSSCompilationSession.java @@ -233,6 +233,11 @@ public class JSCSSCompilationSession extends CSSCompilationSession { builder.append(condition.getConditionType().prefix); builder.append(condition.getValue()); + String args = condition.getArguments(); + if (args != null) + { + builder.append(args); + } } } diff --git a/compiler-jx/src/test/resources/royale/files/CSSTestSource.css b/compiler-jx/src/test/resources/royale/files/CSSTestSource.css index d23c64b31..c68648728 100755 --- a/compiler-jx/src/test/resources/royale/files/CSSTestSource.css +++ b/compiler-jx/src/test/resources/royale/files/CSSTestSource.css @@ -164,6 +164,10 @@ p:not(.primary) { color: #fff; } +:is(ol, ul) { + color: #fff; +} + #my-id ~ h1:first-child span.subtitle { color: #fff; } \ No newline at end of file diff --git a/compiler-jx/src/test/resources/royale/files/CSSTestSource_encoded_result.txt b/compiler-jx/src/test/resources/royale/files/CSSTestSource_encoded_result.txt index 8def6dc56..3b08e57fe 100755 --- a/compiler-jx/src/test/resources/royale/files/CSSTestSource_encoded_result.txt +++ b/compiler-jx/src/test/resources/royale/files/CSSTestSource_encoded_result.txt @@ -151,6 +151,10 @@ function() {this["filter"] = null}, function() {this["color"] = 16777215}, 0, 1, +":is(ol, ul)", +function() {this["color"] = 16777215}, +0, +1, "span.subtitle", function() {this["color"] = 16777215}]; diff --git a/compiler-jx/src/test/resources/royale/files/CSSTestSource_result.css b/compiler-jx/src/test/resources/royale/files/CSSTestSource_result.css index 5a847f95c..1a10074d3 100755 --- a/compiler-jx/src/test/resources/royale/files/CSSTestSource_result.css +++ b/compiler-jx/src/test/resources/royale/files/CSSTestSource_result.css @@ -183,6 +183,11 @@ p:not(.primary) { } +:is(ol, ul) { + color: #fff; +} + + #my-id~h1:first-child span.subtitle { color: #fff; } diff --git a/compiler/src/main/antlr3/org/apache/royale/compiler/internal/css/CSSTree.g b/compiler/src/main/antlr3/org/apache/royale/compiler/internal/css/CSSTree.g index 5f9413103..138f3f0d0 100644 --- a/compiler/src/main/antlr3/org/apache/royale/compiler/internal/css/CSSTree.g +++ b/compiler/src/main/antlr3/org/apache/royale/compiler/internal/css/CSSTree.g @@ -172,6 +172,21 @@ protected static final List<String> KNOWN_FUNCTIONS = Arrays.asList( "xywh" ); +protected static final List<String> KNOWN_PSEUDO_CLASS_FUNCTIONS = Arrays.asList( + "dir", + "has", + "host", + "is", + "lang", + "not", + "nth-child", + "nth-last-child", + "nth-last-of-type", + "nth-of-type", + "state", + "where" +); + /** * CSS DOM object. */ @@ -467,11 +482,12 @@ conditionSelector { ConditionType type = null; String name = null; + String arguments = null; } @after { $simpleSelector::conditions.add( - new CSSSelectorCondition(name, type, $start, tokenStream)); + new CSSSelectorCondition(name, type, arguments, $start, tokenStream)); } : ^(DOT c=ID) { type = ConditionType.CLASS; name = $c.text; } | HASH_WORD { type = ConditionType.ID; name = $HASH_WORD.text.substring(1); } @@ -479,15 +495,16 @@ conditionSelector { if (strictFlexCSS) { - // Flex didn't support the CSS :not() pseudo-class + // Flex didn't support the CSS pseudo-class functions displayStrictFlexSyntaxError($COLON.text + $s.text, $s); } - if (!$s.text.equals("not")) + if (!KNOWN_PSEUDO_CLASS_FUNCTIONS.contains($s.text)) { displayUnknownPseudoClassError($s.text, $s); } - type = ConditionType.NOT; - name = $arg.text; + type = ConditionType.PSEUDO; + name = $s.text; + arguments = $arg.text; } | ^(COLON s=ID) { type = ConditionType.PSEUDO; name = $s.text; } | ^(DOUBLE_COLON dc=ID) diff --git a/compiler/src/main/java/org/apache/royale/compiler/css/ConditionType.java b/compiler/src/main/java/org/apache/royale/compiler/css/ConditionType.java index f538de4b3..a0ae6469d 100644 --- a/compiler/src/main/java/org/apache/royale/compiler/css/ConditionType.java +++ b/compiler/src/main/java/org/apache/royale/compiler/css/ConditionType.java @@ -35,7 +35,7 @@ public enum ConditionType ID("#"), /** - * For example: <code>s|Label:loadingState</code> + * For example: <code>s|Label:loadingState</code> or <code>s|Button:not(.rounded)</code> */ PSEUDO(":"), @@ -44,11 +44,6 @@ public enum ConditionType */ PSEUDO_ELEMENT("::"), - /** - * For example: <code>s|Panel:not(:first-child)</code> - */ - NOT(":not"), - /** * For example: <code>s|Label[loadingState]</code> */ diff --git a/compiler/src/main/java/org/apache/royale/compiler/css/ICSSSelectorCondition.java b/compiler/src/main/java/org/apache/royale/compiler/css/ICSSSelectorCondition.java index b00f130a7..f03ad55c7 100644 --- a/compiler/src/main/java/org/apache/royale/compiler/css/ICSSSelectorCondition.java +++ b/compiler/src/main/java/org/apache/royale/compiler/css/ICSSSelectorCondition.java @@ -41,6 +41,11 @@ public interface ICSSSelectorCondition extends ICSSNode */ String getValue(); + /** + * @return Optional arguments value, or null. + */ + String getArguments(); + /** * @return Condition type. */ diff --git a/compiler/src/main/java/org/apache/royale/compiler/internal/css/CSSSelector.java b/compiler/src/main/java/org/apache/royale/compiler/internal/css/CSSSelector.java index 28fcd153c..e9ea9127a 100644 --- a/compiler/src/main/java/org/apache/royale/compiler/internal/css/CSSSelector.java +++ b/compiler/src/main/java/org/apache/royale/compiler/internal/css/CSSSelector.java @@ -171,6 +171,11 @@ public class CSSSelector extends CSSNodeBase implements ICSSSelector ICSSSelectorCondition condition = conditions.get(i); s.append(condition.getConditionType().prefix); s.append(condition.getValue()); + String args = condition.getArguments(); + if (args != null) + { + s.append(args); + } } return s.toString(); } diff --git a/compiler/src/main/java/org/apache/royale/compiler/internal/css/CSSSelectorCondition.java b/compiler/src/main/java/org/apache/royale/compiler/internal/css/CSSSelectorCondition.java index c53dea955..d94a280e7 100644 --- a/compiler/src/main/java/org/apache/royale/compiler/internal/css/CSSSelectorCondition.java +++ b/compiler/src/main/java/org/apache/royale/compiler/internal/css/CSSSelectorCondition.java @@ -36,16 +36,33 @@ public class CSSSelectorCondition extends CSSNodeBase implements ICSSSelectorCon final ConditionType type, final CommonTree tree, final TokenStream tokenStream) + { + this(value, type, null, tree, tokenStream); + } + + protected CSSSelectorCondition(final String value, + final ConditionType type, + final String arguments, + final CommonTree tree, + final TokenStream tokenStream) { super(tree, tokenStream, CSSModelTreeType.SELECTOR_CONDITION); assert !Strings.isNullOrEmpty(value) : "Selector condition value can't be empty."; assert type != null : "Selector condition type can't be null."; this.value = value; this.type = type; + this.arguments = arguments; } private final String value; private final ConditionType type; + private final String arguments; + + @Override + public String getArguments() + { + return arguments; + } @Override public String getValue() @@ -62,6 +79,11 @@ public class CSSSelectorCondition extends CSSNodeBase implements ICSSSelectorCon @Override public String toString() { - return type.prefix.concat(value); + String result = type.prefix.concat(value); + if (arguments != null) + { + result = result.concat(arguments); + } + return result; } } diff --git a/compiler/src/test/build.xml b/compiler/src/test/build.xml index f508beb73..9981656e7 100644 --- a/compiler/src/test/build.xml +++ b/compiler/src/test/build.xml @@ -318,7 +318,7 @@ <batchtest todir="${compiler}/target/junit-reports"> <fileset dir="${compiler}/target/test-classes"> <include name="**/*Tests.class"/> - <!-- <exclude name="as/**"/> --> + <exclude name="as/**"/> <exclude name="f/**"/> <exclude name="mxml/tags/**"/> <exclude name="properties/**"/> diff --git a/compiler/src/test/java/org/apache/royale/compiler/internal/css/CSSSelectorConditionTests.java b/compiler/src/test/java/org/apache/royale/compiler/internal/css/CSSSelectorConditionTests.java index 5a80b6a14..ec8f3e01d 100644 --- a/compiler/src/test/java/org/apache/royale/compiler/internal/css/CSSSelectorConditionTests.java +++ b/compiler/src/test/java/org/apache/royale/compiler/internal/css/CSSSelectorConditionTests.java @@ -75,6 +75,23 @@ public class CSSSelectorConditionTests extends CSSBaseTests { assertThat("condition.getOperator()" , condition.getOperator(), is( CSSModelTreeType.SELECTOR_CONDITION ) ); assertThat("condition.getConditionType()" , condition.getConditionType() , is( ConditionType.PSEUDO ) ); assertThat("condition.getValue()" , condition.getValue(), is( "up" ) ); + assertThat("condition.getArguments()" , condition.getArguments(), is( (String) null ) ); + } + + + @Test + public void CSSSelectorConditionTests_pseudo_function_condition() + { + String code = " custom|Button:not(.rounded) "; + + List<ICSSSelectorCondition> conditions = getCSSSelectorConditions(code); + assertThat("conditions.size()" , conditions.size(), is(1) ); + + CSSSelectorCondition condition = (CSSSelectorCondition) conditions.get(0); + assertThat("condition.getOperator()" , condition.getOperator(), is( CSSModelTreeType.SELECTOR_CONDITION ) ); + assertThat("condition.getConditionType()" , condition.getConditionType() , is( ConditionType.PSEUDO ) ); + assertThat("condition.getValue()" , condition.getValue(), is( "not" ) ); + assertThat("condition.getArguments()" , condition.getArguments(), is( "(.rounded)" ) ); } @Test @@ -89,6 +106,7 @@ public class CSSSelectorConditionTests extends CSSBaseTests { assertThat("condition.getOperator()" , condition.getOperator(), is( CSSModelTreeType.SELECTOR_CONDITION ) ); assertThat("condition.getConditionType()" , condition.getConditionType() , is( ConditionType.CLASS ) ); assertThat("condition.getValue()" , condition.getValue(), is( "rounded" ) ); + assertThat("condition.getArguments()" , condition.getArguments(), is( (String) null ) ); } @Test @@ -103,6 +121,7 @@ public class CSSSelectorConditionTests extends CSSBaseTests { assertThat("condition.getOperator()" , condition.getOperator(), is( CSSModelTreeType.SELECTOR_CONDITION ) ); assertThat("condition.getConditionType()" , condition.getConditionType() , is( ConditionType.ID ) ); assertThat("condition.getValue())" , condition.getValue(), is( "main" ) ); + assertThat("condition.getArguments()" , condition.getArguments(), is( (String) null ) ); } @Test @@ -117,16 +136,19 @@ public class CSSSelectorConditionTests extends CSSBaseTests { assertThat("condition1.getOperator()" , condition1.getOperator(), is( CSSModelTreeType.SELECTOR_CONDITION ) ); assertThat("condition1.getConditionType()" , condition1.getConditionType() , is( ConditionType.CLASS ) ); assertThat("condition1.getValue()" , condition1.getValue(), is( "rounded" ) ); + assertThat("condition1.getArguments()" , condition1.getArguments(), is( (String) null ) ); CSSSelectorCondition condition2 = (CSSSelectorCondition) conditions.get(1); assertThat("condition2.getOperator()" , condition2.getOperator(), is( CSSModelTreeType.SELECTOR_CONDITION ) ); assertThat("condition2.getConditionType()" , condition2.getConditionType() , is( ConditionType.ID ) ); assertThat("condition2.getValue()" , condition2.getValue(), is( "main" ) ); + assertThat("condition2.getArguments()" , condition2.getArguments(), is( (String) null ) ); CSSSelectorCondition condition3 = (CSSSelectorCondition) conditions.get(2); assertThat("condition3.getOperator()" , condition3.getOperator(), is( CSSModelTreeType.SELECTOR_CONDITION ) ); assertThat("condition3.getConditionType()" , condition3.getConditionType() , is( ConditionType.PSEUDO ) ); assertThat("condition3.getValue()" , condition3.getValue(), is( "up" ) ); + assertThat("condition3.getArguments()" , condition3.getArguments(), is( (String) null ) ); }
