@@ -100,11 +100,18 @@ private function process_picture( OD_HTML_Tag_Processor $processor, OD_Tag_Visit
100100
101101 // Collect <source> elements.
102102 if ( 'SOURCE ' === $ tag && ! $ processor ->is_tag_closer () ) {
103+ $ media = $ processor ->get_attribute ( 'media ' );
104+ $ type = $ processor ->get_attribute ( 'type ' );
105+
106+ // Ensure that all <source> elements have a type attribute and no media attribute.
107+ if ( null !== $ media || null === $ type ) {
108+ return false ;
109+ }
110+
103111 $ collected_sources [] = array (
104112 'srcset ' => $ processor ->get_attribute ( 'srcset ' ),
105113 'sizes ' => $ processor ->get_attribute ( 'sizes ' ),
106- 'type ' => $ processor ->get_attribute ( 'type ' ),
107- 'media ' => $ processor ->get_attribute ( 'media ' ),
114+ 'type ' => $ type ,
108115 'crossorigin ' => $ this ->get_attribute_value ( $ processor , 'crossorigin ' ),
109116 );
110117 }
@@ -127,7 +134,7 @@ private function process_picture( OD_HTML_Tag_Processor $processor, OD_Tag_Visit
127134 return false ;
128135 }
129136
130- $ this ->add_preload_link_for_picture ( $ context , $ img_xpath , $ collected_sources );
137+ $ this ->add_preload_link_for_picture ( $ context , $ img_xpath , $ collected_sources[ 0 ] );
131138
132139 return true ;
133140 }
@@ -250,46 +257,42 @@ private function pre_img_process( OD_HTML_Tag_Processor $processor, OD_Tag_Visit
250257 *
251258 * @since n.e.x.t
252259 *
253- * @param OD_Tag_Visitor_Context $context Tag visitor context.
254- * @param string $xpath XPath of the element.
255- * @param array<int, array {srcset?: string|true|null,sizes?: string|true|null,type?: string|true|null,media?: string|true|null,crossorigin?: string|true|null}> $collected_sources Collected sources from the <source> elements.
260+ * @param OD_Tag_Visitor_Context $context Tag visitor context.
261+ * @param string $xpath XPath of the element.
262+ * @param array{srcset?: string|true|null,sizes?: string|true|null,type?: string|true|null,media?: string|true|null,crossorigin?: string|true|null} $source Collected sources from the <source> elements.
256263 */
257- private function add_preload_link_for_picture ( OD_Tag_Visitor_Context $ context , string $ xpath , array $ collected_sources ): void {
264+ private function add_preload_link_for_picture ( OD_Tag_Visitor_Context $ context , string $ xpath , array $ source ): void {
258265 // If this element is the LCP (for a breakpoint group), add a preload link for it.
259266 foreach ( $ context ->url_metric_group_collection ->get_groups_by_lcp_element ( $ xpath ) as $ group ) {
260- foreach ( $ collected_sources as $ source ) {
261- $ link_attributes = array_merge (
267+ $ link_attributes = array_merge (
268+ array (
269+ 'rel ' => 'preload ' ,
270+ 'fetchpriority ' => 'high ' ,
271+ 'as ' => 'image ' ,
272+ ),
273+ array_filter (
262274 array (
263- 'rel ' => 'preload ' ,
264- 'fetchpriority ' => 'high ' ,
265- 'as ' => 'image ' ,
275+ 'href ' => isset ( $ source ['srcset ' ] ) && is_string ( $ source ['srcset ' ] )
276+ ? explode ( ' ' , $ source ['srcset ' ] )[0 ]
277+ : '' ,
278+ 'imagesrcset ' => isset ( $ source ['srcset ' ] ) && is_string ( $ source ['srcset ' ] ) ? $ source ['srcset ' ] : '' ,
279+ 'imagesizes ' => isset ( $ source ['sizes ' ] ) && is_string ( $ source ['sizes ' ] ) ? $ source ['sizes ' ] : '' ,
280+ 'type ' => isset ( $ source ['type ' ] ) && is_string ( $ source ['type ' ] ) ? $ source ['type ' ] : '' ,
281+ 'media ' => isset ( $ source ['media ' ] ) && is_string ( $ source ['media ' ] ) ? 'screen and ' . $ source ['media ' ] : 'screen ' ,
266282 ),
267- array_filter (
268- array (
269- 'href ' => isset ( $ source ['srcset ' ] ) && is_string ( $ source ['srcset ' ] )
270- ? explode ( ' ' , $ source ['srcset ' ] )[0 ]
271- : '' ,
272- 'imagesrcset ' => isset ( $ source ['srcset ' ] ) && is_string ( $ source ['srcset ' ] ) ? $ source ['srcset ' ] : '' ,
273- 'imagesizes ' => isset ( $ source ['sizes ' ] ) && is_string ( $ source ['sizes ' ] ) ? $ source ['sizes ' ] : '' ,
274- 'type ' => isset ( $ source ['type ' ] ) && is_string ( $ source ['type ' ] ) ? $ source ['type ' ] : '' ,
275- 'media ' => isset ( $ source ['media ' ] ) && is_string ( $ source ['media ' ] ) ? 'screen and ' . $ source ['media ' ] : 'screen ' ,
276- ),
277- static function ( string $ value ): bool {
278- return '' !== $ value ;
279- }
280- )
281- );
282-
283- if ( isset ( $ source ['crossorigin ' ] ) ) {
284- $ link_attributes ['crossorigin ' ] = 'use-credentials ' === $ source ['crossorigin ' ] ? 'use-credentials ' : 'anonymous ' ;
285- }
286-
287- $ context ->link_collection ->add_link (
288- $ link_attributes ,
289- $ group ->get_minimum_viewport_width (),
290- $ group ->get_maximum_viewport_width ()
291- );
283+ static function ( string $ value ): bool {
284+ return '' !== $ value ;
285+ }
286+ )
287+ );
288+ if ( isset ( $ source ['crossorigin ' ] ) ) {
289+ $ link_attributes ['crossorigin ' ] = 'use-credentials ' === $ source ['crossorigin ' ] ? 'use-credentials ' : 'anonymous ' ;
292290 }
291+ $ context ->link_collection ->add_link (
292+ $ link_attributes ,
293+ $ group ->get_minimum_viewport_width (),
294+ $ group ->get_maximum_viewport_width ()
295+ );
293296 }
294297 }
295298
0 commit comments