@@ -180,9 +180,10 @@ public static function parse( string $input, int &$offset );
180180
181181abstract class WP_CSS_Selector_Parser implements IWP_CSS_Selector_Parser, IWP_CSS_Selector_Matcher {
182182 const UTF8_MAX_CODEPOINT_VALUE = 0x10FFFF ;
183+ const WHITESPACE_CHARACTERS = " \t\r\n\f" ;
183184
184185 public static function parse_whitespace ( string $ input , int &$ offset ): bool {
185- $ length = strspn ( $ input , " \t\r\n\f" , $ offset );
186+ $ length = strspn ( $ input , self :: WHITESPACE_CHARACTERS , $ offset );
186187 $ advanced = $ length > 0 ;
187188 $ offset += $ length ;
188189 return $ advanced ;
@@ -698,8 +699,16 @@ public function matches( WP_HTML_Processor $processor ): bool {
698699 : $ att_value === $ this ->value ;
699700
700701 case self ::MATCH_ONE_OF_EXACT :
701- // @todo
702- throw new Exception ( 'One of attribute matching is not supported yet. ' );
702+ foreach ( $ this ->whitespace_delimited_list ( $ att_value ) as $ val ) {
703+ if (
704+ $ case_insensitive
705+ ? 0 === strcasecmp ( $ val , $ this ->value )
706+ : $ val === $ this ->value
707+ ) {
708+ return true ;
709+ }
710+ }
711+ return false ;
703712
704713 case self ::MATCH_EXACT_OR_EXACT_WITH_HYPHEN :
705714 // Attempt the full match first
@@ -727,13 +736,35 @@ public function matches( WP_HTML_Processor $processor ): bool {
727736
728737 case self ::MATCH_CONTAINS :
729738 return false !== (
730- $ case_insensitive ?
731- stripos ( $ att_value , $ this ->value ) :
732- strpos ( $ att_value , $ this ->value )
739+ $ case_insensitive
740+ ? stripos ( $ att_value , $ this ->value )
741+ : strpos ( $ att_value , $ this ->value )
733742 );
734743 }
735744 }
736745
746+ /**
747+ * @param string $input
748+ *
749+ * @return Generator<string>
750+ */
751+ private function whitespace_delimited_list ( string $ input ): Generator {
752+ $ offset = strspn ( $ input , self ::WHITESPACE_CHARACTERS );
753+
754+ while ( $ offset < strlen ( $ input ) ) {
755+ // Find the byte length until the next boundary.
756+ $ length = strcspn ( $ input , self ::WHITESPACE_CHARACTERS , $ offset );
757+ if ( 0 === $ length ) {
758+ return ;
759+ }
760+
761+ $ value = substr ( $ input , $ offset , $ length );
762+ $ offset += $ length + strspn ( $ input , self ::WHITESPACE_CHARACTERS , $ offset + $ length );
763+
764+ yield $ value ;
765+ }
766+ }
767+
737768 /**
738769 * [att=val]
739770 * Represents an element with the att attribute whose value is exactly "val".
0 commit comments