-
Notifications
You must be signed in to change notification settings - Fork 21
Add filtering for each tag after adding the loading attribute #10
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -32,10 +32,8 @@ | |||||
function _wp_lazy_loading_initialize_filters() { | ||||||
// The following filters would be merged into core. | ||||||
foreach ( array( 'the_content', 'the_excerpt', 'comment_text', 'widget_text_content' ) as $filter ) { | ||||||
// Before parsing blocks and shortcodes. | ||||||
// TODO: Comments do not support images. Revisit. | ||||||
// TODO: This should not exclude images from dynamic blocks and shortcodes. Look at fixing the filter priority. | ||||||
add_filter( $filter, 'wp_add_lazy_load_attributes', 8 ); | ||||||
// After parsing blocks and shortcodes. | ||||||
add_filter( $filter, 'wp_add_lazy_load_attributes', 25 ); | ||||||
} | ||||||
|
||||||
// The following filters are only needed while this is a feature plugin. | ||||||
|
@@ -141,14 +139,36 @@ function wp_add_lazy_load_attributes( $content, $context = null ) { | |||||
|
||||||
return preg_replace_callback( | ||||||
'/<img\s[^>]+>/', | ||||||
function( array $matches ) { | ||||||
function( array $matches ) use( $content, $context ) { | ||||||
if ( ! preg_match( '/\sloading\s*=/', $matches[0] ) ) { | ||||||
return str_replace( '<img', '<img loading="lazy"', $matches[0] ); | ||||||
$tag_html = $matches[0]; | ||||||
|
||||||
/** | ||||||
* Filters the `loading` attribute value. Default `lazy`. | ||||||
* | ||||||
* Returning `false` or an empty string will not add the attribute. | ||||||
* Returning `true` will add the default value. | ||||||
* | ||||||
* @since (TBD) | ||||||
* | ||||||
* @param string $default The filtered value, defaults to `lazy`. | ||||||
* @param string $tag_html The tag's HTML. | ||||||
* @param string $content The HTML containing the image tag. | ||||||
* @param string $context Optional. Additional context. Defaults to `current_filter()`. | ||||||
*/ | ||||||
$value = apply_filters( 'wp_set_image_loading_attr', 'lazy', $tag_html, $content, $context ); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think passing contextual data here is good, but I'm a bit wary of passing the content here. Anything this could be used for is probably to run another regex, which isn't something we should encourage. It would be great to have a post ID or potentially attachment ID, but since neither is passed to here, and it may be unreliable or expensive to get these, maybe we should just leave it out for now and only pass This is something where maybe we can enhance in the future, but I'd prefer to leave out There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder whether we should remove the
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Don't think this is a good idea. Having more context in filters/actions makes them more useful. If we remove it, and a plugin has to get the context in order to work, the only option would be to disable core's functionality, copy the code to the plugin and "tweak" it so it works. That brings a lot more problems down the line. Why would we want to "restrict" the context and not support edge cases? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This filter isn't specially useful, as not all the tags on put through this function.. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Same as above. Less context means less useful hooks :)
Not exactly. Currently this is "enable/disable lazy-loading globally for img tags in specific context". It is not particularly useful at the moment, would eventually become more useful if/when lazy-loading for iframes is added to the specs. However removing the context makes it even less useful. Thinking that without context there's no point of having it at all at the moment.
Right. However there are some inconsistencies:
Passing more context about why, where, how it runs would cover more cases and generally make it more useful. "Restricting" the context means that plugins won't be able to use it in certain cases. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Generally yes, but not really in this case IMO. It would help distinguish what these two filters should be used for. One would be for enabling/disabling the feature for a specific HTML element overall, the other would be for controlling per image. Removing There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Yes, ideally that should have been the case. Unfortunately |
||||||
|
||||||
if ( $value ) { | ||||||
if ( ! in_array( $value, array( 'lazy', 'eager' ), true ) ) { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd prefer if we didn't check for a whitelist of values here, as it's overly strict and makes maintenance on our end harder. As the spec evolves (e.g. there's still a good chance for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, not sure how potentially adding another value makes maintenance harder? I mean, if the specs are changed and/or we have to change the default value in WP, we can commit it today and do a minor release tomorrow. This is one of the advantages of adding the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't think this is a good idea. If we wanted plugins to be able to add "unrestricted HTML" there, better to filter the whole There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We would need to use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, |
||||||
$value = 'lazy'; | ||||||
} | ||||||
|
||||||
return str_replace( '<img', '<img loading="' . $value . '"', $tag_html ); | ||||||
} | ||||||
} | ||||||
|
||||||
return $matches[0]; | ||||||
}, | ||||||
$content | ||||||
); | ||||||
} | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you give your thinking on why you chose 25 as priority specifically?
Looping in @spacedmonkey because he originally set it to 8.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
25 is somewhat arbitrary for "after all other default filters".
Not sure why it was set to 8, but that means we were not adding the attribute to images added with shortcodes, like to the (old style) galleries, etc. Running it "early" means it misses few cases where images may be added, don't see why these images should be skipped.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
8 was set because this filter should be applied before blocks are rendered.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the reason to exclude dynamic and rendered blocks? Did you run into some troubles with any of them?
Generally thinking we want the attribute on all images in all cases. Then, if there are cases where lazy-loading doesn't work well, find a way to skip adding it if possible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not applying these filters early is the desired behaviour here. Adding this attribute to rendered blocks, shortcodes and other filtered content as we have no idea what effect that will have on third party code. I think they would be breakages and backlash if we opt everyone in. Take for example a tracking pixel loaded in via a shortcode or block. If this is then lazy loaded, then it would be a breakage.
We should make sure all core functionality like galleries shortcodes supports lazy loading attribute. We should also have a way for third party code to opt in.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the main purpose of this plugin, to test such cases. Frankly I don't see much difference between HTML content added by the users directly (may be pasted, etc.) and HTML content added by plugins. Excluding images that may be added by the user using a plugin that adds a shortcode or a specific block is not a good idea imho, at least for now. If any breakage is detected during testing, lets look at the specific cases.
(Having said that, we are running late... Looks like this feature will miss WP 5.4 if this plugin is not released asap, as there will not be sufficient time to test).
This case is specifically discussed in the HTML specs. Also, as the browser downloads the first 2KB of each image, tracking pixels will work regardless of the attribute or its value (these images are usually smaller than 2KB anyway).