@@ -9,41 +9,44 @@ public class ConditionParser : IConditionParser
99 /// <summary>
1010 /// Based on https://www.w3.org/TR/CSS21/grammar.html (see also https://www.w3.org/TR/CSS22/grammar.html)
1111 /// Limitations:
12- /// - Unicode escape characters are not supported.
1312 /// - Multiple selectors are not supported.
1413 /// </summary>
15- private static Regex SimpleCssIdSelectorRegex = new Regex ( @"^#(?<name>(?<nmchar>[_a-z0-9-]|[\240-\377]|(?<escape>\\[^\r\n\f0-9a-f]))+)$" , RegexOptions . Compiled | RegexOptions . IgnoreCase ) ;
14+ private static Regex SimpleCssIdSelectorRegex = new Regex ( @"^#(?<name>(?<nmchar>[_a-z0-9-]|[\240-\377]|(?<escape>\\[^\r\n\f0-9a-f])|(?<unicode>\\[0-9a-fA-F]{1,6}\s?) )+)$" , RegexOptions . Compiled | RegexOptions . IgnoreCase ) ;
1615
1716 /// <summary>
1817 /// Based on https://www.w3.org/TR/CSS21/grammar.html (see also https://www.w3.org/TR/CSS22/grammar.html)
1918 /// Limitations:
20- /// - Unicode escape characters are not supported.
2119 /// - Multiple selectors are not supported.
2220 /// </summary>
23- private static Regex SimpleCssClassSelectorRegex = new Regex ( @"^\.(?<ident>-?(?<nmstart>[_a-z]|[\240-\377])(?<nmchar>[_a-z0-9-]|[\240-\377]|(?<escape>\\[^\r\n\f0-9a-f]))*)$" , RegexOptions . Compiled | RegexOptions . IgnoreCase ) ;
21+ private static Regex SimpleCssClassSelectorRegex = new Regex ( @"^\.(?<ident>-?(?<nmstart>[_a-z]|[\240-\377])(?<nmchar>[_a-z0-9-]|[\240-\377]|(?<escape>\\[^\r\n\f0-9a-f])|(?<unicode>\\[0-9a-fA-F]{1,6}\s?) )*)$" , RegexOptions . Compiled | RegexOptions . IgnoreCase ) ;
2422
2523 /// <summary>
2624 /// Based on https://www.w3.org/TR/CSS21/grammar.html (see also https://www.w3.org/TR/CSS22/grammar.html)
2725 /// Limitations:
28- /// - Unicode escape characters or escape characters in the attribute name are not supported.
26+ /// - Escape characters in the attribute name are not supported.
2927 /// - Multiple selectors are not supported.
3028 /// - Attribute presence selector (e.g. `[name]`) not supported.
3129 /// - Attribute equals attribute (e.g. `[name=value]`) not supported.
3230 /// - ~= or |= not supported.
3331 /// </summary>
34- private static Regex SimpleCssAttributeSelectorRegex = new Regex ( @"^\*?\[\s*(?<ident>-?(?<nmstart>[_a-z]|[\240-\377])(?<nmchar>[_a-z0-9-]|[\240-\377])*)\s*=\s*(?<string>(?<string1>""(?<string1value>([^\n\r\f\\""]|(?<escape>\\[^\r\n\f0-9a-f])) *)"")|(?<string2>'(?<string2value>([^\n\r\f\\']|(?<escape>\\[^\r\n\f0-9a-f]))*)'))\s*\]$" , RegexOptions . Compiled | RegexOptions . IgnoreCase ) ;
32+ private static Regex SimpleCssAttributeSelectorRegex = new Regex ( @"^\*?\[\s*(?<ident>-?(?<nmstart>[_a-z]|[\240-\377])(?<nmchar>[_a-z0-9-]|[\240-\377])*)\s*=\s*(?<string>(?<string1>""(?<string1value>([^\n\r\f\\""]|(?<escape>\\[^\r\n\f0-9a-f])|(?<unicode>\\[0-9a-fA-F]{1,6}\s?)) *)"")|(?<string2>'(?<string2value>([^\n\r\f\\']|(?<escape>\\[^\r\n\f0-9a-f])|(?<unicode>\\[0-9a-fA-F]{1,6}\s? ))*)'))\s*\]$" , RegexOptions . Compiled | RegexOptions . IgnoreCase ) ;
3533
3634 /// <summary>
3735 /// Based on https://www.w3.org/TR/CSS21/grammar.html (see also https://www.w3.org/TR/CSS22/grammar.html)
38- /// Limitations:
39- /// - Unicode escape characters are not supported.
36+ /// Matches simple escape characters (e.g., \#)
4037 /// </summary>
4138 private static Regex SimpleCssEscapeCharacterRegex = new Regex ( @"\\[^\r\n\f0-9a-f]" , RegexOptions . Compiled | RegexOptions . IgnoreCase ) ;
4239
40+ /// <summary>
41+ /// Matches CSS unicode escape sequences (e.g., \34 or \000034 followed by optional space)
42+ /// </summary>
43+ private static Regex CssUnicodeEscapeRegex = new Regex ( @"\\([0-9a-fA-F]{1,6})\s?" , RegexOptions . Compiled ) ;
44+
4345 public PropertyCondition ParseCondition ( ConditionFactory conditionFactory , string @using , string value )
4446 {
4547 switch ( @using )
4648 {
49+ case "id" :
4750 case "accessibility id" :
4851 return conditionFactory . ByAutomationId ( value ) ;
4952 case "name" :
@@ -86,8 +89,16 @@ public PropertyCondition ParseCondition(ConditionFactory conditionFactory, strin
8689
8790 private static string ReplaceCssEscapedCharacters ( string value )
8891 {
89- return SimpleCssEscapeCharacterRegex . Replace ( value , match => match . Value . Substring ( 1 ) ) ;
90- }
92+ var result = CssUnicodeEscapeRegex . Replace ( value , m =>
93+ {
94+ var hexValue = m . Groups [ 1 ] . Value ;
95+ var decodedChar = ( ( char ) Convert . ToInt32 ( hexValue , 16 ) ) . ToString ( ) ;
96+ return decodedChar ;
97+ } ) ;
9198
99+ result = SimpleCssEscapeCharacterRegex . Replace ( result , match => match . Value . Substring ( 1 ) ) ;
100+
101+ return result ;
102+ }
92103 }
93104}
0 commit comments