Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve hero image determination #6062

Merged
merged 22 commits into from
Apr 15, 2021

Conversation

westonruter
Copy link
Member

@westonruter westonruter commented Apr 9, 2021

Summary

Fixes #6061

  • Enable DetermineHeroImages transformer by default, instead of just for the core themes.
  • Introduce HeroCandidateFiltering service which uses WP filters to automatically add data-hero-candidate attribute to images output via get_custom_logo(), get_header_image_tag(), and the wp_get_attachment_image() when the attachment image is the featured image of the queried object or first the post in the loop.
  • Remove featured image and (mostly) custom logo handling from DetermineHeroImages since better handled now by HeroCandidateFiltering.
  • Update DetermineHeroImages to identify all images before main or the first .entry-content as being header images, but omit images which were originally marked as loading=lazy. Include even tiny images which have logo in the class name.
  • Extend prerendering of first-content blocks to include images in blocks other than Cover block and Image block (e.g. YouTube embed placeholders).

Depends on:

Checklist

  • My code is tested and passes existing tests.
  • My code follows the Engineering Guidelines (updates are often made to the guidelines, check it out periodically).

@westonruter westonruter added this to the v2.1 milestone Apr 9, 2021
@codecov
Copy link

codecov bot commented Apr 10, 2021

Codecov Report

Merging #6062 (be3dba3) into develop (905ca69) will increase coverage by 0.08%.
The diff coverage is 97.10%.

❗ Current head be3dba3 differs from pull request most recent head 67a2f91. Consider uploading reports for the commit 67a2f91 to get more accurate results
Impacted file tree graph

@@              Coverage Diff              @@
##             develop    #6062      +/-   ##
=============================================
+ Coverage      74.81%   74.89%   +0.08%     
- Complexity      5771     5782      +11     
=============================================
  Files            230      231       +1     
  Lines          17492    17505      +13     
=============================================
+ Hits           13087    13111      +24     
+ Misses          4405     4394      -11     
Flag Coverage Δ Complexity Δ
javascript 79.84% <ø> (ø) 0.00 <ø> (ø)
php 74.67% <97.10%> (+0.08%) 5782.00 <25.00> (+11.00)

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ Complexity Δ
...udes/sanitizers/class-amp-core-theme-sanitizer.php 36.54% <0.00%> (+0.26%) 227.00 <0.00> (-1.00) ⬆️
src/AmpWpPlugin.php 100.00% <ø> (ø) 9.00 <0.00> (ø)
src/Optimizer/Transformer/DetermineHeroImages.php 98.07% <97.05%> (+7.03%) 24.00 <12.00> (-1.00) ⬆️
src/Optimizer/AmpWPConfiguration.php 100.00% <100.00%> (ø) 5.00 <0.00> (ø)
src/Optimizer/HeroCandidateFiltering.php 100.00% <100.00%> (ø) 13.00 <13.00> (?)
src/Infrastructure/ServiceBasedPlugin.php 86.20% <0.00%> (+0.68%) 56.00% <0.00%> (ø%)

@@ -109,50 +100,64 @@ public function transform( Document $document, ErrorCollection $errors ) { // ph
}

if ( $candidate instanceof DOMElement ) {
$hero_image_elements[] = $candidate;
$hero_image_elements[ spl_object_hash( $candidate ) ] = $candidate;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The use of spl_object_hash() allows for the removal of duplicates.

@westonruter westonruter requested a review from schlessera April 10, 2021 05:49
@westonruter westonruter force-pushed the fix/hero-image-candidate-determination branch from 731b690 to e8ea9c0 Compare April 11, 2021 05:44
@westonruter westonruter force-pushed the fix/hero-image-candidate-determination branch from e8ea9c0 to cb443cc Compare April 11, 2021 05:58
@westonruter westonruter force-pushed the fix/hero-image-candidate-determination branch from cb443cc to 5100cd4 Compare April 11, 2021 06:46
Comment on lines 82 to 84
case 'featured_image':
$candidate = $this->get_featured_image( $document );
break;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's an issue here with the featured image. Namely, if there is a template with multiple posts on it, and the first post lacks a featured image but the second post has one, then this featured image will get prerendered:

image

This issue is mitigated by preserving the loading=lazy on the original img as done in ampproject/amp-toolbox-php#149 but it is not ideal. Consider this worse case where there is a content image in the first post, but a featured image in the second. The featured image from the second post will win out over the content image in the first:

image

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See also an e-commerce example (apparently using Astra and WooCommerce) in which the hero image is not marked up as a featured image, nor is it inside of .entry-content. Rather, it has a selector main > div.ast-woocommerce-container > div.product-section > div > div > div:nth-child(1) > div > amp-img.

This makes me think that we should perhaps eliminate the featured image check, in favor of getting the first images from the main element as hero candidates, or if no main then the first .hentry.

@westonruter
Copy link
Member Author

Importantly, there is now a maxHeroImageCount parameter in the OptimizeHeroImages to override the default max of 2: ampproject/amphtml#30442 (comment). This depends on ampproject/amp-toolbox-php#55.

In a WordPress context, I think we should go ahead and SSR every image that has loading=lazy if that attribute is persisted on the amp-img[i-amphtml-ssr]>img.

We could limit SSR of hero images to 2 if they lack loading=lazy.

@westonruter
Copy link
Member Author

I think we need to augment the transformer with regular WordPress hooks. Namely, we should add data-hero-candidate via PHP filters for header image, custom logo, and the featured image of the queried object and/or first post in the loop. This will be a more reliable way of detecting these hero images by having insider knowledge from WordPress. This would run in addition to the logic currently in DetermineHeroImages, so we'd identify images using filters and then anything that slipped past the filters could be identified with XPath queries.

…image-candidate-determination

* 'develop' of github.com:ampproject/amp-wp: (31 commits)
  Update snapshots and fix tests
  Remove references to AMP 'page' since it may be post; harmonize strings
  Use boolean return type for isDevToolsEnabled selector
  Add missing name prop for PluginDocumentSettingPanel in AMPDocumentSettingPanel
  Show AMP Validation sidebar button when all issues have been reviewed
  Omit AMPToolbarButton when AMP is not enabled
  Make entry path regex match simpler
  Show AMP toggle when Dev Tools are disabled
  Remove redundant build:css script
  Improve JS test coverage
  Ignore block editor plugins from test coverage
  Ignore block editor plugins in unit test
  Add more unit tests
  Fix broken E2E test
  Do not generate empty JS chunks for stylesheets
  Omit DependencyExtractionWebpackPlugin for CSS
  Add `build:css` back so that CI continues to work
  Move the entrypoint config so that it is in alphabetical order
  Handle CSS build process with Webpack
  Add unit tests to AMPDocumentStatusNotification
  ...
…image-candidate-determination

* 'develop' of github.com:ampproject/amp-wp: (27 commits)
  Remove unused $matches
  Avoid failing validation requests when response is redirect
  Undo erroneous addition of is_callable() check in d0d2137
  Improve static analysis and formatting
  Catch UnknownConfigurationClass exception when transformer has no config
  Avoid alignment using tabs
  Remove double blank lines
  Fix test failure caused by new amp-onerror script
  Fix code style issue
  Revert sorting the services array
  Add transformer config command
  Add transformer list command
  Fix code style issues
  Use injected optimizer service
  Complete docblock
  Add optimizer command
  Refactor registration of CLI commands to be integrated with the service container
  Refactor validation command into PSR-4 service-based architecture
  Test whether optimizer gets caching and fallback downloads
  Add AmpWPConfiguration test
  ...
@westonruter westonruter marked this pull request as ready for review April 14, 2021 23:59
@westonruter westonruter requested a review from pierlon April 15, 2021 00:00
@github-actions
Copy link
Contributor

github-actions bot commented Apr 15, 2021

Plugin builds for 67a2f91 are ready 🛎️!

.phpstorm.meta.php Show resolved Hide resolved
Comment on lines 293 to +295
// Twenty Ten.
case 'twentyten':
return [
'enable_determine_hero_images_transformer' => [],
];
return [];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose the twentyten case can be removed then?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried removing but then I got warnings:

[15-Apr-2021 03:16:16 UTC] PHP Warning:  array_merge(): Expected parameter 2 to be an array, null given in /app/public/content/plugins/amp/includes/sanitizers/class-amp-core-theme-sanitizer.php on line 495
[15-Apr-2021 03:16:16 UTC] PHP Warning:  Invalid argument supplied for foreach() in /app/public/content/plugins/amp/includes/sanitizers/class-amp-core-theme-sanitizer.php on line 499

So it's currently needed, due to how that array is used in the get_theme_features method.

src/Optimizer/AmpWPConfiguration.php Outdated Show resolved Hide resolved
src/Optimizer/HeroCandidateFiltering.php Show resolved Hide resolved
westonruter and others added 2 commits April 14, 2021 20:14
Co-authored-by: Pierre Gordon <16200219+pierlon@users.noreply.github.com>
src/Optimizer/HeroCandidateFiltering.php Show resolved Hide resolved
}

/** @covers ::add_data_hero_candidate_attribute() */
public function add_data_hero_candidate_attribute() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test was not being executed.

Suggested change
public function add_data_hero_candidate_attribute() {
public function test_add_data_hero_candidate_attribute() {

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops! Committed your suggestion in this commit: 67a2f91

/** @covers ::add_data_hero_candidate_attribute() */
public function add_data_hero_candidate_attribute() {
$this->assertEquals(
$array_with_attr,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$array_with_attr is undefined here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😊 Fixed in 67a2f91

Co-authored-by: Pierre Gordon <16200219+pierlon@users.noreply.github.com>
Copy link
Contributor

@pierlon pierlon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quite an impressive feat achieved here, LGTM!

@westonruter westonruter merged commit a1bc12f into develop Apr 15, 2021
@westonruter westonruter deleted the fix/hero-image-candidate-determination branch April 15, 2021 04:58
* @return bool Whether the conditional object is needed.
*/
public static function is_needed() {
return amp_is_request();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll have to pay attention to this one. It means we need to ensure in the CLI context that we need to ensure this evaluates to true, otherwise these filters will be missing.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. It will always be false in a WP-CLI context currently:

// Short-circuit for cron, CLI, admin requests or requests to non-frontend pages.
if ( wp_doing_cron() || ( defined( 'WP_CLI' ) && WP_CLI ) || is_admin() || in_array( $pagenow, [ 'wp-login.php', 'wp-signup.php', 'wp-activate.php', 'repair.php' ], true ) ) {
return false;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Use loading=lazy as a signal for images to skip as candidates in DetermineHeroImages transformer
3 participants