Essential metrics for a healthy site.
ampproject/amp-wp 1582
Enable AMP on your WordPress site, the WordPress way.
Site Kit is a one-stop solution for WordPress users to use everything Google has to offer to make them successful on the web.
The AMP Project Website.
WordPress feature plugin to bring Progressive Web Apps (PWA) to Core
Web Stories for WordPress
GoogleChromeLabs/wp-sitemaps 93
Proposal to integrate basic XML Sitemaps in WordPress Core
GoogleChromeLabs/wordpressdev 61
WordPress development environment for core, plugins, and themes, based on Lando.
luehrsenheinrich/wp-quicklink 49
The WordPress plugin for quicklink. ⚡️Faster subsequent page-loads by prefetching in-viewport links during idle time.
GoogleChromeLabs/wp-native-lazyload 48
WordPress plugin to lazy-load media using the native browser feature.
pull request commentampproject/amp-wp
Run phpstan on staged PHP source files
I did test. It caught an issue with a staged file.
comment created time in 11 hours
issue commentAutomattic/jetpack
Remaining fix for Image Compare block: #17254
comment created time in 11 hours
issue commentAutomattic/jetpack
Image Compare Block: No caption in AMP
PR to fix: #17254
comment created time in 11 hours
PR opened Automattic/jetpack
Fixes #16858 See #14395
The Image Compare block on AMP pages was not including not only the caption but also the containing figure.wp-block-jetpack-image-compare wrapper element. This PR fixes that problem by just replacing the div.juxtapose element inside the block $content with the amp-image-slider element, rather than just rendering just the amp-image-slider alone.
Before

AMP markup for block:
<amp-image-slider layout="responsive" width="1536" height="2048">
<amp-img id="4175" src="https://wordpressdev.lndo.site/content/uploads/2020/09/fire-before.jpg" alt="" layout="fill"></amp-img>
<amp-img id="4176" src="https://wordpressdev.lndo.site/content/uploads/2020/09/fire-after.jpg" alt="" layout="fill"></amp-img>
</amp-image-slider>
After

AMP markup for block:
<figure class="wp-block-jetpack-image-compare">
<amp-image-slider layout="responsive" width="1536" height="2048">
<amp-img id="4175" src="https://wordpressdev.lndo.site/content/uploads/2020/09/fire-before.jpg" alt="" layout="fill"></amp-img>
<amp-img id="4176" src="https://wordpressdev.lndo.site/content/uploads/2020/09/fire-after.jpg" alt="" layout="fill"></amp-img>
</amp-image-slider>
<figcaption>Before and after the wildfire smoke in Portland, Oregon</figcaption>
</figure>
Changes proposed in this Pull Request:
<!--- Explain what functional changes your PR includes -->
- Include caption and original block wrapper element for Image Compare block on AMP pages.
Jetpack product discussion
<!-- If you're an Automattician, include a shortlink to the p2 discussion with Jetpack Product here. --> <!-- Make sure any changes to existing products have been discussed and agreed upon -->
Does this pull request change what data or activity we track or use?
<!--- If so, please add the "[Status] Needs Privacy Updates" label and explain what changes there are. --> <!--- Check existing Jetpack support documents for a preview of the information we need. -->
Testing instructions:
<!-- If you were reviewing this PR, how would you like the instructions to be presented? --> <!-- Please include detailed testing steps, explaining how to test your change. --> <!-- Bear in mind that context you working on is not obvious for everyone. --> <!-- Adding "simple" configuration steps will help reviewers to get to your PR as quickly as possible. --> <!-- "Before / After" screenshots can also be very helpful when the change is visual. -->
- Add an Image Compare block to a post, along with a caption.
- View the post on an AMP page.
Proposed changelog entry for your changes:
<!-- Please do not leave this empty. If no changelog entry needed, state as such. -->
- Preserve caption for Image Compare blocks on AMP pages.
pr created time in 11 hours
create barnchwestonruter/jetpack
branch : fix/amp-image-compare-caption
created branch time in 12 hours
issue commentAutomattic/jetpack
Image Compare Block: AMP Errors
In looking at \Automattic\Jetpack\Extensions\ImageCompare\render_amp(), the issue seems to be that it is supplying no width or height when there is no width or height supplied:
https://github.com/Automattic/jetpack/blob/3a551cbe3a56b93a89ed60a012059a865ee1fbf1/extensions/blocks/image-compare/image-compare.php#L61-L63
This is not valid AMP, as all elements need to have sizing. I suggest a fallback width/height of 1. Since since the layout is responsive, this will have the effect of making the element sized to fit its container as a square (1:1 aspect ratio).
comment created time in 12 hours
Pull request review commentAutomattic/jetpack
Image Compare: set width and height attributes for block's images
function render_amp( $attr ) { $img_after = $attr['imageAfter']; return sprintf(- '<amp-image-slider layout="responsive" width="%1$d" height="%2$d"> <amp-img id="%3$d" src="%4$s" alt="%5$s" layout="fill"></amp-img> <amp-img id="%6$d" src="%7$s" alt="%8$s" layout="fill"></amp-img></amp-image-slider>',- absint( $img_before['width'] ),- absint( $img_before['height'] ),+ '<amp-image-slider layout="responsive"%1$s%2$s> <amp-img id="%3$d" src="%4$s" alt="%5$s" layout="fill"></amp-img> <amp-img id="%6$d" src="%7$s" alt="%8$s" layout="fill"></amp-img></amp-image-slider>',+ ! empty( $img_before['width'] ) ? ' width="' . absint( $img_before['width'] ) . '"' : '',+ ! empty( $img_before['height'] ) ? ' height="' . absint( $img_before['height'] ) . '"' : '',
This caused a regression: #16093.
Note: In AMP if the width/height are not available, instead of omitting the attributes (since they are required in AMP), the solution is to provide fallback width and height. See proposed fix in #17253.
comment created time in 12 hours
issue commentAutomattic/jetpack
Image Compare Block: AMP Errors
PR to fix: #17253
comment created time in 12 hours
issue commentAutomattic/jetpack
PR to fix part of Image Compare: #17253
comment created time in 12 hours
PR opened Automattic/jetpack
Fixes #16093 See #14395
All elements in AMP need to have dimensions defined up-front so that the page will have static layout to avoid CLS (Cumulative Layout Shift). When no width or height is available for the Image Compare block, instead of omitting the width/height for the amp-image-slider component, the correct AMP fallback is to provide fallback dimensions. Since we don't know what the image dimension is, providing an aspect ratio of 1:1 seems to make sense.
Changes proposed in this Pull Request:
<!--- Explain what functional changes your PR includes -->
- Ensure fallback dimensions are provided to Image Compare block when image size is not available
Jetpack product discussion
<!-- If you're an Automattician, include a shortlink to the p2 discussion with Jetpack Product here. --> <!-- Make sure any changes to existing products have been discussed and agreed upon -->
Does this pull request change what data or activity we track or use?
<!--- If so, please add the "[Status] Needs Privacy Updates" label and explain what changes there are. --> <!--- Check existing Jetpack support documents for a preview of the information we need. -->
Testing instructions:
<!-- If you were reviewing this PR, how would you like the instructions to be presented? --> <!-- Please include detailed testing steps, explaining how to test your change. --> <!-- Bear in mind that context you working on is not obvious for everyone. --> <!-- Adding "simple" configuration steps will help reviewers to get to your PR as quickly as possible. --> <!-- "Before / After" screenshots can also be very helpful when the change is visual. -->
Add an Image Compare block to a post and view that post on an AMP page.
I'm not sure entirely why the width or height weren't available when calling render_amp(), so the only way I know to test this is to forcibly unset them when calling the function:
unset( $img_before['width'], $img_before['height'] );
Proposed changelog entry for your changes:
<!-- Please do not leave this empty. If no changelog entry needed, state as such. -->
- Fix AMP implementation of Image Compare block
pr created time in 12 hours
create barnchwestonruter/jetpack
branch : fix/image-compare-block-amp-fallback-dimensions
created branch time in 12 hours
issue commentAutomattic/jetpack
Revue widget makes illegal cross-domain call in AMP mode
This will be fixed with https://github.com/ampproject/amp-wp/issues/4191
The proposed solution I've worked on (which needs to be picked up again) is to implement a local proxy endpoint when a form is pointing to an external domain so that the CORS headers aren't an issue. This will also ensure that redirects work properly. See https://github.com/ampproject/amp-wp/pull/4212.
comment created time in 12 hours
issue commentampproject/amp-wp
Issue with Genesis eNews Extended form
This is also needed by the Revue widget in Jetpack: https://github.com/Automattic/jetpack/issues/16922.
comment created time in 12 hours
issue commentAutomattic/jetpack
PR for Contact Form: #17252
comment created time in 13 hours
issue commentAutomattic/jetpack
@brbrr Here's a PR to fix that: #17252
comment created time in 13 hours
PR opened Automattic/jetpack
Fixes #15981 See #14395
Fixes styling of Contact Forms on the legacy AMP post template in Reader mode. This is only an issue in legacy Reader mode because the old post templates do not have The Loop, and thus loop_start does not fire.
| Before | After |
|---|---|
![]() |
![]() |
Changes proposed in this Pull Request:
<!--- Explain what functional changes your PR includes -->
- Fix styling of Contact Forms in legacy AMP Reader mode post templates.
Jetpack product discussion
<!-- If you're an Automattician, include a shortlink to the p2 discussion with Jetpack Product here. --> <!-- Make sure any changes to existing products have been discussed and agreed upon -->
Does this pull request change what data or activity we track or use?
<!--- If so, please add the "[Status] Needs Privacy Updates" label and explain what changes there are. --> <!--- Check existing Jetpack support documents for a preview of the information we need. -->
Testing instructions:
<!-- If you were reviewing this PR, how would you like the instructions to be presented? --> <!-- Please include detailed testing steps, explaining how to test your change. --> <!-- Bear in mind that context you working on is not obvious for everyone. --> <!-- Adding "simple" configuration steps will help reviewers to get to your PR as quickly as possible. --> <!-- "Before / After" screenshots can also be very helpful when the change is visual. -->
- Add a contact form to a post.
- Activate the AMP plugin.
- Switch to Reader mode and select the "AMP Legacy" Reader theme.
- View the post as AMP.
Proposed changelog entry for your changes:
<!-- Please do not leave this empty. If no changelog entry needed, state as such. -->
- Fix styling of Contact Forms in legacy AMP Reader mode post templates.
pr created time in 13 hours
create barnchwestonruter/jetpack
branch : fix/contact-form-amp-styling
created branch time in 13 hours
Pull request review commentAutomattic/jetpack
Google Calendar block: Fix full width support
function register_block() { * @return string */ function load_assets( $attr ) {- $width = isset( $attr['width'] ) ? $attr['width'] : '800'; $height = isset( $attr['height'] ) ? $attr['height'] : '600'; $url = isset( $attr['url'] ) ? \Jetpack_Gutenberg::validate_block_embed_url( $attr['url'], array( 'calendar.google.com' ) ) : ''; $classes = \Jetpack_Gutenberg::block_classes( 'google-calendar', $attr ); + \Jetpack_Gutenberg::load_assets_as_required( 'google-calendar' );+ if ( empty( $url ) ) { return; } if ( class_exists( 'Jetpack_AMP_Support' ) && \Jetpack_AMP_Support::is_amp_request() ) { return sprintf(- '<div class="%1$s"><amp-iframe src="%2$s" frameborder="0" style="border:0" scrolling="no" width="%3$d" height="%4$d" sandbox="allow-scripts allow-same-origin" layout="responsive"></amp-iframe></div>',+ '<div class="%1$s"><amp-iframe src="%2$s" frameborder="0" style="border:0" scrolling="no" height="%3$d" sandbox="allow-scripts allow-same-origin" layout="responsive"></amp-iframe></div>',
This change appears to have broken Google Calendar on AMP pages, since there is no width defined, and the layout was not changed from responsive to fixed-height. Opened PR to fix in #17251.
comment created time in 13 hours
issue commentAutomattic/jetpack
PR for Google Calendar block: https://github.com/Automattic/jetpack/pull/17251
comment created time in 13 hours
PR opened Automattic/jetpack
See #14395
Given this post_content:
<!-- wp:separator -->
<hr class="wp-block-separator"/>
<!-- /wp:separator -->
<!-- wp:jetpack/google-calendar {"url":"https://calendar.google.com/calendar/embed?src=askenergy%40oregon.gov\u0026ctz=America/Los_Angeles"} -->
<a href="https://calendar.google.com/calendar/embed?src=askenergy%40oregon.gov&ctz=America/Los_Angeles" class="wp-block-jetpack-google-calendar">https://calendar.google.com/calendar/embed?src=askenergy%40oregon.gov&ctz=America/Los_Angeles</a>
<!-- /wp:jetpack/google-calendar -->
<!-- wp:separator -->
<hr class="wp-block-separator"/>
<!-- /wp:separator -->
Google Calendar is currently not rendering at all on an AMP page. This is because it is getting removed due to not having a width defined on the amp-iframe:
This PR fixes that issue by supplying the proper layout of fixed-height rather than responsive, since the width is intended to be 100%. (This appears to be a regression introduced in #14835.) Also missing in the previous implementation was the placeholder child which is required for amp-iframe elements appearing in the initial viewport. So a link to the Google Calendar was supplied as a placeholder in this case.
This PR also goes beyond just fixing AMP compatibility in that the page is actually better than the non-AMP version when JS is turned off, by supplying a the plain HTML calendar view to visitors with JS turned off. Some additional AMP-specific CSS was included here, but that will eventually not be needed once those are accounted for in AMP itself. See https://github.com/ampproject/amphtml/pull/29846.
Before
| Non-AMP w/ JS | Non-AMP w/o JS | AMP 👎 | AMP w/o JS 👎 |
|---|---|---|---|
![]() |
![]() |
(Removed by plugin sanitizer) |
(Removed by plugin sanitizer) |
After
| Non-AMP w/ JS | Non-AMP w/o JS | AMP 👍 | AMP w/o JS 👍 |
|---|---|---|---|
(No change) |
(No change) |
![]() |
(No-JS fallback!) |
Changes proposed in this Pull Request:
<!--- Explain what functional changes your PR includes -->
- Fix AMP compatibility in Google Calendar block.
Jetpack product discussion
<!-- If you're an Automattician, include a shortlink to the p2 discussion with Jetpack Product here. --> <!-- Make sure any changes to existing products have been discussed and agreed upon -->
Does this pull request change what data or activity we track or use?
<!--- If so, please add the "[Status] Needs Privacy Updates" label and explain what changes there are. --> <!--- Check existing Jetpack support documents for a preview of the information we need. -->
Testing instructions:
<!-- If you were reviewing this PR, how would you like the instructions to be presented? --> <!-- Please include detailed testing steps, explaining how to test your change. --> <!-- Bear in mind that context you working on is not obvious for everyone. --> <!-- Adding "simple" configuration steps will help reviewers to get to your PR as quickly as possible. --> <!-- "Before / After" screenshots can also be very helpful when the change is visual. -->
- Copy the above
post_contentinto a new post. - Activate the AMP plugin and enable Transitional mode.
- Compare the post in AMP and non-AMP (e.g. via Paired Browsing).
Proposed changelog entry for your changes:
<!-- Please do not leave this empty. If no changelog entry needed, state as such. -->
- Fix AMP compatibility in Google Calendar block.
pr created time in 13 hours
create barnchwestonruter/jetpack
branch : add/google-calendar-amp-compat
created branch time in 14 hours
push eventampproject/amp-wp
commit sha 07f32713b637176793def38131df8e643143f1af
Update dependency lint-staged to v10.4.0
commit sha ead16c715703020fd371b308026a90914edcb948
Merge pull request #5419 from renovate-bot/renovate/lint-staged-10.x Update dependency lint-staged to v10.4.0
push time in 14 hours
PR merged ampproject/amp-wp
This PR contains the following updates:
| Package | Type | Update | Change |
|---|---|---|---|
| lint-staged | devDependencies | minor | 10.3.0 -> 10.4.0 |
Release Notes
<details> <summary>okonet/lint-staged</summary>
v10.4.0
Features
</details>
Renovate configuration
:date: Schedule: At any time (no schedule defined).
:vertical_traffic_light: Automerge: Disabled by config. Please merge this manually once you are satisfied.
:recycle: Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
:no_bell: Ignore: Close this PR and you won't be reminded about this update again.
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box
This PR has been generated by WhiteSource Renovate. View repository job log here.
pr closed time in 14 hours
push eventampproject/amp-wp
commit sha 89d4e52dab107141861bce12bf053162ea305f82
Update dependency eslint-plugin-react to v7.21.1
commit sha 31c6ead1eb63913e20d927b5adf6e91bdedb1dbe
Merge pull request #5418 from renovate-bot/renovate/eslint-plugin-react-7.x Update dependency eslint-plugin-react to v7.21.1
push time in 14 hours
PR merged ampproject/amp-wp
This PR contains the following updates:
| Package | Type | Update | Change |
|---|---|---|---|
| eslint-plugin-react | devDependencies | minor | 7.20.6 -> 7.21.1 |
Release Notes
<details> <summary>yannickcr/eslint-plugin-react</summary>
v7.21.1
Fixed
- [
jsx-handler-names]: avoid a crash when an inline prop is not a MemberExpression (#2803 @willheslam)
v7.21.0
Added
- [
button-has-type]: support trivial ternary expressions (#2748 @Hypnosphi) - [
jsx-handler-names]: addcheckInlineFunctionoption (#2761 @dididy) - [
jsx-no-literals]: addnoAttributeStringsoption (#2782 @TaLeaMonet) - [
prop-types]: add support forPropTypes.exact(#2740 @jzabala) - [
jsx-filename-extension]: Add allow option (#2746 @remcohaszing)
Fixed
- [
function-component-definition]: ignore object properties (#2771 @stefan-wullems) - [
forbid-component-props]: Implemented support for "namespaced" components (#2767 @mnn) - [
prefer-read-only-props]: support Flow$ReadOnly(#2772, #2779, #2770 @karolina-benitez) - [
jsx-handler-names]: handle whitespace (#2789 @AriPerkkio) - [
prop-types]: Detect TypeScript types for destructured default prop values (#2780 @sunghyunjo) - [
jsx-pascal-case]: Handle single character namespaced component (#2791 @daviferreira) - [
jsx-closing-bracket-location]: Intag-aligned, made a distinction between tabs and spaces (#2796 @Moong0122) - [
jsx-handler-names]: false positive when handler name begins with number (#1689 @jsphstls) - [
prop-types]: Detect JSX returned by sequential expression (#2801 @mikol) - [
jsx-props-no-multi-spaces]: "Expected no line gap between" false positive (#2792 @karolina-benitez) - [
no-unknown-property]: check attributes with any input case (#2790 @julienw) - [
prop-types]/[no-unused-prop-types]: handle CallExpression in ReturnType (#2802 @hank121314) - [
jsx-uses-react]: mark fragment variables as used (#2775 @remcohaszing) - [
no-unused-prop-types]: improve component declared props detection ([#2755][] @jzabala) - [
jsx-props-no-multi-spaces]: Show error in multi-line props (#2756 @iiison)
Changed
- [Tests][
jsx-one-expression-per-line]: add passing tests (#2799 @TaLeaMonet) - [Tests][
prop-types]: add test (#2757 @jzabala)
</details>
Renovate configuration
:date: Schedule: At any time (no schedule defined).
:vertical_traffic_light: Automerge: Disabled by config. Please merge this manually once you are satisfied.
:recycle: Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
:no_bell: Ignore: Close this PR and you won't be reminded about this update again.
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box
This PR has been generated by WhiteSource Renovate. View repository job log here.
pr closed time in 14 hours
push eventampproject/amp-wp
commit sha 70da394df3eac29fe66189ecd3835a2d43c63ef3
Fix undefined index notice for some layout error titles (#5425)
push time in 16 hours
push eventampproject/amp-wp
commit sha 1cec3dd591600b8ab42fa10f8fc939da80a63c78
Fix undefined index notice for some layout error titles (#5425)
push time in 16 hours
delete branch ampproject/amp-wp
delete branch : fix/error-title-for-auto-width-error
delete time in 16 hours
PR merged ampproject/amp-wp
Summary
I was testing the Google Calendar block in Jetpack and there was a validation error, but there was also a PHP notice at the same time:
<b>Notice</b>: Undefined index: width in <b>/app/public/content/plugins/amp/includes/validation/class-amp-validation-error-taxonomy.php</b> on line <b>3226</b>
The HTML block being validated indeed lacked a width:
<div class="wp-block-jetpack-google-calendar"><iframe src="https://calendar.google.com/calendar/embed?src=askenergy%40oregon.gov&ctz=America/Los_Angeles" frameborder="0" style="border:0" scrolling="no" height="600"></iframe></div>
So this needs to not be assumed when we construct the error title. This PR adds the necessary isset() check.
| Before | After |
|---|---|
![]() |
![]() |
Checklist
- [ ] My pull request is addressing an open issue (please create one otherwise).
- [ ] 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).
pr closed time in 16 hours
push eventampproject/amp-wp
commit sha fb6fed543df7b8d734080a9c15d9eb0740450c13
Fix undefined index notice for some layout error titles
push time in 17 hours
PR opened ampproject/amp-wp
Summary
I was testing the Google Calendar block in Jetpack and there was a validation error, but there was also a PHP notice at the same time:
<b>Notice</b>: Undefined index: width in <b>/app/public/content/plugins/amp/includes/validation/class-amp-validation-error-taxonomy.php</b> on line <b>3226</b>
The HTML block being validated indeed lacked a width:
<div class="wp-block-jetpack-google-calendar"><iframe src="https://calendar.google.com/calendar/embed?src=fobmuamv2c7cu19aq1n2gc6p8c0p90ur%40import.calendar.google.com&ctz=America%2FLos_Angeles" frameborder="0" style="border:0" scrolling="no" height="600"></iframe></div>
So this needs to not be assumed when we construct the error title. This PR adds the necessary isset() check.
| Before | After |
|---|---|
![]() |
![]() |
Checklist
- [ ] My pull request is addressing an open issue (please create one otherwise).
- [ ] 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).
pr created time in 17 hours
create barnchampproject/amp-wp
branch : fix/error-title-for-auto-width-error
created branch time in 17 hours
push eventampproject/amp-wp
commit sha 3e4af0c7d8b17a128343c68063fe6ae78ac0c22f
Run phpstan on staged PHP source files
commit sha d61923e4def2718d315e9ed639b54088f9e07e41
Merge pull request #5424 from ampproject/enhancement/static-analysis-on-staged-files Run phpstan on staged PHP source files
push time in 18 hours
delete branch ampproject/amp-wp
delete branch : enhancement/static-analysis-on-staged-files
delete time in 18 hours
PR merged ampproject/amp-wp
Summary
This PR is a followup from #4441, which runs phpstan on staged PHP files within the includes or src folders.
Checklist
- [ ] My pull request is addressing an open issue (please create one otherwise).
- [ ] 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).
pr closed time in 18 hours
push eventwestonruter/jetpack
commit sha 97cd2092ad18009f07c98bcb778783dc1d663fe7
Adding clip-path property to supported CSS properties (#17178)
commit sha ad8ec79d5b67572e4b6d10ac8e08a542186c4032
Prevent adding adding AMP hooks for Infinite Scroll on legacy AMP post templates (#17175)
commit sha 3f961e599bf981006a9e07405fe46ad068d85cf4
Update dependency preact to v10.4.8 (#17082) Co-authored-by: Renovate Bot <[email protected]>
commit sha 8c77f8b0703f8d26226fa09d9e0b51167553975b
Update dependency swiper to v6.2.0 (#16770) Co-authored-by: Renovate Bot <[email protected]>
commit sha 6c5efe71c326a52af39656fdf41a5cd4654b59a5
Update dependency jsdom to v16.4.0 (#16849) Co-authored-by: Renovate Bot <[email protected]>
commit sha 1c5b9c3622e06bb523b07f03e57bef2274144e4f
Update dependency eslint to v7.9.0 (#17080) Co-authored-by: Renovate Bot <[email protected]>
commit sha 944f0d233db82d76e5d0cfd757ae68b17288da4a
E2E Tests: Update to support new plans (#17186) * Update E2E tests to support new plans * minor fix * fix pro blocks * return true when block is found * [not verified] [not verified] Improve Support for Jetpack Complete & Security Plans (#17177) Cherry-picked from https://github.com/Automattic/jetpack/pull/17177 Co-authored-by: Caleb Bauermeister <[email protected]>
commit sha e0c2edfd61f7ab1edd854e106de6e3dd1298f1e8
8.9.1: add changelog (#17107)
commit sha 508e933ad8321921a7edccc60468e024808bb570
Blocks: add new methods to new package (#17126) Co-authored-by: Brad Jorsch <[email protected]>
commit sha 0fba989e34db2fdfcba543e23e13a647f6323151
Gutenboarding: save selected features as a site option (#17169) Summary: This patch is part of [[ 45148-gh-wp-calypso | #45148 ]] This patch saves the `selected_features` as a site option. We're looking to use this data during the Site setup flow (in editor) to recommend a plan based on the selected features. The option will be available only for sites created using `site_creation_flow: 'gutenboarding'`. Note: this change is a very similar to D42191-code Test Plan: Follow testing instructions in [[ 45148-gh-wp-calypso | #45148 ]] Reviewers: simison, mciampini, tomjcafferkey Reviewed By: mciampini, tomjcafferkey Tags: #touches_jetpack_files Differential Revision: D49420-code This commit syncs r213657-wpcom.
commit sha d06a8b7557165ee52644c085ed9755a628e6dd93
CodeClimate test: update node version (#17168) This needs to be done following the change in #14274, so the version used in the CodeClimate test matches the version expected for the build.
commit sha 6903d4f18be177221158ad84bf4eb79886f0a5aa
Autoloader: Detect filtering of active_plugins (#17174)
commit sha 5e12db68d3e8c540c69e728a1e8f99decb4d4a14
Embeds: Instagram: Allow setting own access token to bypass proxied requests (#17185)
commit sha 4262c1491c8c9299af836b6977dd29bb760b3059
Google Analytics: Move legacy code to head (#17184)
commit sha 0c3b3fcfdf66680adaa795d79a6e58344a2f94ce
a8c-mc-stats: Do not distribute test files (#17183)
commit sha 422091abff9011b6e59e7e4913bb09a947fc4bbd
Update dependency css-loader to v4.3.0 (#17022) Co-authored-by: Renovate Bot <[email protected]>
commit sha d7e15e38382868f870024c0831f56ddc733c83c8
Filter only specific Wikimedia subdomains in Photon API (#17197) Some wikimedia subdomains are hosted on WPVIP and need to be able to use Photon API
commit sha aae801388df8405075aec910522ef177eedaf7dc
Jetpack_IXR_ClientMulticall: Fix sort_calls() producing undefined relative order between equal items (#17009)
commit sha 371fe20e6a221ef98d75f82caf2ed0556abb8f59
Build: Update vulnerable dependencies (#17074) * resolve security vulnerablities in dependencies * Cleanup resolutions * add `bl` resolution * add node-fetch into yarn resolutions
commit sha 8f8104179df236101209af8f71aef3e70d06d340
Crowdsignal: Don't call mktime() in a deprecated manner. (#17199)
push time in 18 hours
push eventampproject/amp-wp
commit sha c0860b608113502c951c9906f4c2c3fd57811173
Update dependency grunt to v1.3.0
commit sha 77666c82cde98f91031b6f6af735cad98f80b853
Merge pull request #4995 from renovate-bot/renovate/grunt-1.x Update dependency grunt to v1.3.0
push time in 19 hours
PR merged ampproject/amp-wp
This PR contains the following updates:
| Package | Type | Update | Change |
|---|---|---|---|
| grunt (source) | devDependencies | minor | 1.2.0 -> 1.3.0 |
Release Notes
<details> <summary>gruntjs/grunt</summary>
v1.3.0
- Merge pull request #1720 from gruntjs/update-changelog-deps
faab6be - Update Changelog and legacy-util dependency
520fedb - Merge pull request #1719 from gruntjs/yaml-refactor
7e669ac - Switch to use
safeLoadfor loading YML files viafile.readYAML.e350cea - Merge pull request #1718 from gruntjs/legacy-log-bumo
7125f49 - Bump legacy-log
00d5907
v1.2.1
- Changelog update
ae11839 - Merge pull request #1715 from sibiraj-s/remove-path-is-absolute
9d23cb6 - Remove path-is-absolute dependency
e789b1f
</details>
Renovate configuration
:date: Schedule: At any time (no schedule defined).
:vertical_traffic_light: Automerge: Disabled by config. Please merge this manually once you are satisfied.
:recycle: Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
:no_bell: Ignore: Close this PR and you won't be reminded about this update again.
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box
This PR has been generated by WhiteSource Renovate. View repository job log here.
pr closed time in 19 hours
push eventampproject/amp-wp
commit sha 68001ae0d8ca3fa73185653d6b78dc616100f1b5
Update dependency postcss to v8.0.9
commit sha a3b0aba0fe92513016ab13651a9643bcb53d965d
Merge pull request #5422 from renovate-bot/renovate/postcss-8.x Update dependency postcss to v8.0.9
push time in 19 hours
PR merged ampproject/amp-wp
This PR contains the following updates:
| Package | Type | Update | Change |
|---|---|---|---|
| postcss (source) | devDependencies | patch | 8.0.8 -> 8.0.9 |
Release Notes
<details> <summary>postcss/postcss</summary>
v8.0.9
- Replace prototype in PostCSS 7 nodes instead of recreating them.
- Added missed
Transformerto exported types (by Pierre-Marie Dartus).
</details>
Renovate configuration
:date: Schedule: At any time (no schedule defined).
:vertical_traffic_light: Automerge: Disabled by config. Please merge this manually once you are satisfied.
:recycle: Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
:no_bell: Ignore: Close this PR and you won't be reminded about this update again.
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box
This PR has been generated by WhiteSource Renovate. View repository job log here.
pr closed time in 19 hours
push eventampproject/amp-wp
commit sha 076009dc24de069756ac55e4a5a8a6574bb965cb
Update dependency terser-webpack-plugin to v4
commit sha dc8a3293fd54998db6421d949382f52257c3ed2a
Merge pull request #5163 from renovate-bot/renovate/terser-webpack-plugin-4.x Update dependency terser-webpack-plugin to v4
push time in 19 hours
PR merged ampproject/amp-wp
This PR contains the following updates:
| Package | Type | Update | Change |
|---|---|---|---|
| terser-webpack-plugin | devDependencies | major | 3.1.0 -> 4.2.2 |
Release Notes
<details> <summary>webpack-contrib/terser-webpack-plugin</summary>
v4.2.2
v4.2.1
v4.2.0
Features
Bug Fixes
v4.1.0
Features
- pass license files as related assets for webpack@5 (7d3ae95)
Bug Fixes
- compatibility with
10.13version ofNode.js
v4.0.0
⚠ BREAKING CHANGES
- the
warningsFilteroption was removed without replacement, terserversion is5,- return value of the
minifyoption was changed, onlycode/map/extractedCommentsare valid
Features
- improved compatibility with webpack@5
</details>
Renovate configuration
:date: Schedule: At any time (no schedule defined).
:vertical_traffic_light: Automerge: Disabled by config. Please merge this manually once you are satisfied.
:recycle: Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
:no_bell: Ignore: Close this PR and you won't be reminded about this update again.
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box
This PR has been generated by WhiteSource Renovate. View repository job log here.
pr closed time in 19 hours
pull request commentAutomattic/jetpack
Add AMP compatibility for OpenTable block
@jeherve No longer [Status] Blocked / Hold.
comment created time in a day
push eventwestonruter/jetpack
commit sha ed69db2282f6ae74227afb3ca28bb87c69d00912
Jetpack_WPES_Search_Query_Parser: add method to retrieve lang suffix Summary: Addresses the following issues with the cards endpoint: * Score was not being returned for site recs * Score formatting was inconsistent * Language was not being provided to recommendation classes so all recs were English Test Plan: Use the API console and request v2 /read/tags/cards. Try using a different locale and ensure that you get site recommendations for the right language, e.g. `/read/tags/cards?tags=dogs,cats&sort=popularity&page=1&_locale=fr` Reviewers: gibrown, charlescearl Reviewed By: gibrown Tags: #touches_jetpack_files Differential Revision: D48544-code This commit syncs r213167-wpcom.
commit sha 9740e6dd4b7a0b309825bbc51af8b03de7da0dfe
Earn: Stripe Connection Feedback Message (#17079)
commit sha 8d9329c600e86de0f2fed6a356d8d7003a59d6bb
Update jest monorepo (#17083) Co-authored-by: Renovate Bot <[email protected]>
commit sha e245daa4d4b9553e1a378a091c6ae01ebc853ade
Update dependency eslint-plugin-jsdoc to v30.3.2 (#17081) Co-authored-by: Renovate Bot <[email protected]>
commit sha c1e64768b25a0b8751365c1070c0998b3e7bb9d5
Update icon property on all form variations (#17092) * Update icon property on all form variations Simplifies the icon property to have just a single value instead of an object where `src` and `foreground` were being passed onto. This formatting is not supported, nor are color changes in the variations selections (yet?). * Remove unused getIconColor import * Clean up "Send a message" block icon
commit sha d1fee2411de34ca572c87ea119819b0a9d53ec60
Live Branches Tool: add AMP plugin (#17088)
commit sha 7f6412425766c17555128b919281eab3116760a2
OpenTable Block: Add mobile fallback when using wide style (#16833) * Replace OpenTable wide style widget with standard when viewing via mobile
commit sha c9de96bf26e099c31756803814e4845fac94715e
Add AMP compatibility for Pinterest block (#17086) Co-authored-by: Jeremy Herve <[email protected]>
commit sha f438233624c074bf4cc54755d7397d706cb801d3
Embeds: update song.link oEmbed to support more formats. (#17095)
commit sha 45faac438915f7bb8947ee934f71a68a744677fd
Pinterest: avoid errors when Jetpack_AMP_Support isn't available (#17098)
commit sha 2ea74258933b56b0210acb7bbcef3fb936f377f6
Form Block: remove newsletter variation on wpcom simple sites (#17061)
commit sha cde3db04b6494f99c0df8989db7e84ae6b6b9918
Remove SSO JITM from Jetpack_SSO (#17077)
commit sha 73144eee334d871b116425156644e5df2b6c33ee
Blocks: introduce new package for block management (#17100) See #17099
commit sha 843d05603566e213a6d43ef4c2c9316f2cd9bdb1
Signature Class: Adds support for nested query strings (#17058) Also adds corresponding unit tests.
commit sha 414c0705e05a4148967dd27f657e3851496210d5
Tracking: fix the logic for determining when to enable tracking. (#17076)
commit sha 087af895a140187d32bd4326b60fcae05521588a
Debugger: Add token health check test (#17028) * Debugger: Add token health check test * Debugger: Fix message for test__check_if_connected failing case
commit sha 4d1a94f4622e0edbea6c93af247e3ef5face6c98
Added options to sync wc whitelist (#17075) This commit adds the options `woocommerce_task_list_hidden` and `woocommerce_onboarding_profile` to sync wc whitelist. Co-authored-by: Fernando Marichal <[email protected]>
commit sha 7769a2ffd72823067b3391ef9197bb3fdfca6ad8
Docker MySQL: Slow Queries Log (#17103) - logging of MySQL queries slower than 0.5 second into the file docker/logs/mysql/slow.log - docker/config/mysql.conf config file makes changing the MySQL server configuration easier
commit sha e31d275232488c9e152869996bea6d69feeba0b2
fixes copy post not copying categories in old dbs (#17102)
commit sha e0dd0b9e531da02d7003e953a25e49b30a7cdbac
Sync: stop trying to check for edit_comment capability (#17114) * Sync: switch to checking for capability to edit all comments Checking for edit_comment can only be used to check for the cap for one specific comment, which does not match our needs here. moderate_comments will allow us to check for the ability to edit all comments on the site. More dicussion: p1599656662345700-slack-jetpack-crew * Remove moderate_comments, it's already in the array
push time in a day
Pull request review commentAutomattic/jetpack
Add AMP compatibility for Eventbrite block
const FEATURE_NAME = 'eventbrite'; const BLOCK_NAME = 'jetpack/' . FEATURE_NAME; +/**+ * Determine whether the page will be AMP.+ *+ * @return bool+ */+function is_amp_request() {+ return class_exists( 'Jetpack_AMP_Support' ) && \Jetpack_AMP_Support::is_amp_request();+}
Done in 99e2c2f
comment created time in a day
Pull request review commentAutomattic/jetpack
Add AMP compatibility for Eventbrite block
function render_block( $attr, $content ) { ); $widget_id = wp_unique_id( 'eventbrite-widget-' );-- wp_enqueue_script( 'eventbrite-widget', 'https://www.eventbrite.com/static/widgets/eb_widgets.js', array(), JETPACK__VERSION, true );-- // Add CSS to hide direct link.- Jetpack_Gutenberg::load_assets_as_required( FEATURE_NAME );+ $is_amp = is_amp_request(); // Show the embedded version. if ( empty( $attr['useModal'] ) && ( empty( $attr['style'] ) || 'modal' !== $attr['style'] ) ) {+ return render_embed_block( $widget_id, $is_amp, $attr );+ } else {+ return render_modal_block( $widget_id, $is_amp, $attr, $content );+ }+}++/**+ * Render block with embed style.+ *+ * @param string $widget_id Widget ID to use.+ * @param bool $is_amp Whether AMP page.+ * @param array $attr Eventbrite block attributes.+ * @return string Rendered block.+ */+function render_embed_block( $widget_id, $is_amp, $attr ) {++ // $content contains a fallback link to the event that's saved in the post_content.+ // Append a div that will hold the iframe embed created by the Eventbrite widget.js.+ $classes = Jetpack_Gutenberg::block_classes( FEATURE_NAME, $attr );
Done!
comment created time in a day
push eventwestonruter/jetpack
commit sha c1e93146f81831a0215f3294072d0e27f01b9b51
Infinite scroll for AMP (#16048) Co-authored-by: Jeremy Herve <[email protected]>
commit sha a6dd259c9d1b8f7508626e57d400bd162957b518
Update dependency husky to v4.3.0 (#17148) Co-authored-by: Renovate Bot <[email protected]>
commit sha 68166d3f2845ffe398c7e24780198ff5cdc8853a
Update dependency eslint-plugin-jsdoc to v30.4.2 (#17147) Co-authored-by: Renovate Bot <[email protected]>
commit sha 4abe1df2a4ad13258f67bfafd654d08051daa7f8
E2E Tests: Fix WPORG login failures (#17131) * Wait for navigation before looking for a failed login * add 1ms delay between typing characters
commit sha 40e2c3f49324fa9fefa54c31674ab2ef27451d82
Build Artifacts: fix `nvm` not found issue (#17152) * run `nvm install` * add test steps * add nvm install one more time * Try set `-eo pipefail` * add `shell` definition into `build jetpack` step * try install nvm manually * try exporting nvm stuff * maybe like this? * lets try this one * cleanup * use ubuntu 20.04 * bunch of logging commands * . * .. * add nvm install into build jetpack step * revert back to ubuntu-latest * ... * :shrug: * . * . * .. * add `type -a nvm` * add `type -a nvm` pt 2 * run `nvm use` * run nvm install * maybe this will help :shrug: * Lets try `bash` * install nvm within script * lets try this * . * nvm install * try to move nvm install from script * final version
commit sha 49815210f347db08392569874f1c2dbb350ed10a
CodeClimate: update rules with newer version (#17153)
commit sha fe55c81651d2dbefa63cb6e9bc29f87707988b3a
Adding 'review' to whitelisted comment types (#17141)
commit sha ab9aeb0ea9d028f51e1d776d1d97853f35ab8302
Connection: Initializing default constants for the REST authorization. (#17158) When Jetpack plugin is not installed, REST Authentication requires defaults constants to function. In particular, `JETPACK__API_VERSION` is empty, making the WP Proxy request signature verification fail. This commit: - Extracts the default constants initialization code into `Utils::init_default_constants()`. - Replaces the existing initialization with the new function call. - Adds a new initialization call for `Rest_Authentication` class so WP proxy requests signature could be properly verified.
commit sha 9c670b5651e31a5faf857ff8c441b0049a528c4f
Local Testing Suite: Skip the blog token test if site is not connected (#17163)
commit sha 4400bed51e57a7a413f9e52381c44e8f1cbc9ec5
Update dependency @automattic/social-previews to v1.1.0 (#17146) Co-authored-by: Renovate Bot <[email protected]>
commit sha f4ec85a5b38814576c555b13ee482a86fc024389
Fix early returns in Jetpack. (#17142) Barry: "Summary: We can't call switch_to_blog() and then return without also calling restore_current_blog(). One of these seems very old and the other one seems relatively new in class.media-extractor.php. It seems like we should be able to do some static or dynamic analysis to detect these cases and prevent new ones from being committed." Props @barry for the fix.
commit sha ec48e84b8d68162e0bb7d70cc4cf28c2a63c94ab
Client admin page: Add reconnect route (#17155) * Client: Trigger reconnection with 'reconnect' query parameter * Client admin page: Add reconnect route * Reconnect flow: Hide connection errors and link account notice while reconnecting * Reconnect flow: Stop dispatching SITE_RECONNECT_SUCCESS before page reload Stop dispatching SITE_RECONNECT_SUCCESS before page load so that remains true and the UX unaffected. When becomes true, the UI blur effect goes away and the connection error notices re-appear
commit sha 97cd2092ad18009f07c98bcb778783dc1d663fe7
Adding clip-path property to supported CSS properties (#17178)
commit sha ad8ec79d5b67572e4b6d10ac8e08a542186c4032
Prevent adding adding AMP hooks for Infinite Scroll on legacy AMP post templates (#17175)
commit sha 3f961e599bf981006a9e07405fe46ad068d85cf4
Update dependency preact to v10.4.8 (#17082) Co-authored-by: Renovate Bot <[email protected]>
commit sha 8c77f8b0703f8d26226fa09d9e0b51167553975b
Update dependency swiper to v6.2.0 (#16770) Co-authored-by: Renovate Bot <[email protected]>
commit sha 6c5efe71c326a52af39656fdf41a5cd4654b59a5
Update dependency jsdom to v16.4.0 (#16849) Co-authored-by: Renovate Bot <[email protected]>
commit sha 1c5b9c3622e06bb523b07f03e57bef2274144e4f
Update dependency eslint to v7.9.0 (#17080) Co-authored-by: Renovate Bot <[email protected]>
commit sha 944f0d233db82d76e5d0cfd757ae68b17288da4a
E2E Tests: Update to support new plans (#17186) * Update E2E tests to support new plans * minor fix * fix pro blocks * return true when block is found * [not verified] [not verified] Improve Support for Jetpack Complete & Security Plans (#17177) Cherry-picked from https://github.com/Automattic/jetpack/pull/17177 Co-authored-by: Caleb Bauermeister <[email protected]>
commit sha e0c2edfd61f7ab1edd854e106de6e3dd1298f1e8
8.9.1: add changelog (#17107)
push time in a day
issue commentampproject/amp-wp
As discussed just now, let's also include the hero preloading logic detection for CSS background images that are defined with inline style attributes. For example, the Cover Image block in core is rendered on an AMP page as follows:

In the same way that a transformer is looking for amp-img@src, amp-video@poster, amp-iframe > amp-img (and amp-youtube per https://github.com/ampproject/amp-wp/pull/5350/files#r485283525), it can also look for any element @style (or @data-amp-original-style) to extract the background-image URL, as another candidate for the hero image.
One complication here is that an element with an inline CSS background could be tiny, and we'd have no way of using isTinyElement to detect whether it is too small to be a candidate. Perhaps this interplays with whether the element has data-hero as referenced in https://github.com/ampproject/amp-wp/pull/5350#issuecomment-697298463. Otherwise, we could have WP-specific support, so we'd automatically consider elements that have wp-block-* as a class name to be considered to be not tiny.
comment created time in a day
issue commentampproject/amphtml
Add @-moz-document to the CSS at-rule allowlist
- Allow
@-moz-documentin AMP format (I doubt email would allow this anyway due to the browser sniffing capability) without validation on the url-prefix bit. This is a small, few-line change.
I understand from Bug 1035091 that Mozilla removed support for @-moz-document entirely in Firefox 59, and then via Bug 1446470 it re-added support but only recognizes url-prefix() with an empty value. So the only concern would be for users running Firefox older than v59. I'm not sure where to find detailed browser stats broken down by version, but my assumption is that there are exceedingly small number of users still running such older versions since it has auto-updates. Firefox 59 came out in March 2018—over 2 years ago.
- Add validator support for understanding and validating the remainder of the @ rule parse syntax and validate that we allow only with empty
url-prefixas suggested. This is a larger change, requiring more time allocated, but doable.
If not 1, then this is my preference.
comment created time in a day
Pull request review commentampproject/amp-wp
Add PreloadHeroImage Optimizer transformer
+<?php++namespace AmpProject\Optimizer\Transformer;++use AmpProject\Amp;+use AmpProject\Attribute;+use AmpProject\Dom\Document;+use AmpProject\Extension;+use AmpProject\Layout;+use AmpProject\Optimizer\Configuration\PreloadHeroImageConfiguration;+use AmpProject\Optimizer\Error;+use AmpProject\Optimizer\ErrorCollection;+use AmpProject\Optimizer\HeroImage;+use AmpProject\Optimizer\ImageDimensions;+use AmpProject\Optimizer\Transformer;+use AmpProject\Optimizer\TransformerConfiguration;+use AmpProject\Tag;+use AmpProject\Url;+use DOMElement;+use DOMNode;++/**+ * PreloadHeroImage - this transformer optimizes image rendering times for hero images. For hero images it will:+ *+ * 1. Inject a preload hint (if possible)+ * 2. Generate an img tag enabling the browser to render the image without the AMP runtime being loaded.+ *+ * Hero images are either identified automatically or can be explicitly defined by adding an `data-hero` attribute to+ * the element.+ *+ * This transformer supports the following options:+ *+ * * `preloadHeroImage`: [true|false] - enables or disables hero image preloading. The default is `true`.+ *+ * This is ported from the NodeJS optimizer.+ *+ * @version 3429af9d91e2c9efe1af85757499e5a308755f5f+ * @link https://github.com/ampproject/amp-toolbox/blob/3429af9d91e2c9efe1af85757499e5a308755f5f/packages/optimizer/lib/transformers/PreloadHeroImage.js+ *+ * @package ampproject/optimizer+ */+final class PreloadHeroImage implements Transformer+{++ /**+ * Class(es) to apply to a serverside-rendered image element.+ *+ * @var string+ */+ const SSR_IMAGE_CLASS = 'i-amphtml-fill-content i-amphtml-replaced-content';++ /**+ * List of attributes to copy onto an SSR'ed image.+ *+ * @var string[]+ */+ const ATTRIBUTES_TO_COPY = [+ Attribute::ALT,+ Attribute::ATTRIBUTION,+ Attribute::OBJECT_FIT,+ Attribute::OBJECT_POSITION,+ Attribute::REFERRERPOLICY,+ Attribute::SRC,+ Attribute::SRCSET,+ Attribute::SIZES,+ Attribute::TITLE,+ ];++ /**+ * Maximum number of hero images defined via data-hero attribute.+ *+ * @var int+ */+ const DATA_HERO_MAX = 2;++ /**+ * Configuration store to use.+ *+ * @var TransformerConfiguration+ */+ private $configuration;++ /**+ * Instantiate a PreloadHeroImage object.+ *+ * @param TransformerConfiguration $configuration Configuration store to use.+ */+ public function __construct(TransformerConfiguration $configuration)+ {+ $this->configuration = $configuration;+ }++ /**+ * Apply transformations to the provided DOM document.+ *+ * @param Document $document DOM document to apply the transformations to.+ * @param ErrorCollection $errors Collection of errors that are collected during transformation.+ * @return void+ */+ public function transform(Document $document, ErrorCollection $errors)+ {+ if ($this->configuration->get(PreloadHeroImageConfiguration::PRELOAD_HERO_IMAGE) === false) {+ return;+ }++ $heroImages = $this->findHeroImages($document);+ $referenceNode = $document->viewport;++ $heroImageCount = count($heroImages);+ if ($heroImageCount > self::DATA_HERO_MAX) {+ $errors->add(Error\TooManyHeroImages::whenPastMaximum());+ $heroImageCount = self::DATA_HERO_MAX;+ }++ $isAmpStory = Amp::isAmpStory($document);++ for ($index = 0; $index < $heroImageCount; $index++) {+ $this->generatePreload($heroImages[$index], $document, $errors, $referenceNode);+ $this->generateImg($heroImages[$index], $document);+ }+ }++ /**+ * Find the hero images to optimize.+ *+ * @param Document $document Document to look for hero images in.+ * @return HeroImage[] Array of hero images to optimize.+ */+ private function findHeroImages(Document $document)+ {+ $heroImageCandidate = null;+ $heroImages = [];+ $node = $document->body;++ while ($node !== null) {+ if (! $node instanceof DOMElement) {+ $node = $this->nextNode($node);+ continue;+ }++ $heroImage = $this->detectImageWithDataHero($node);+ if ($heroImage) {+ $heroImages[] = $heroImage;+ }++ if (! $heroImageCandidate && count($heroImages) === 0) {+ $heroImageCandidate = $this->detectHeroImageCandidate($node);+ }+ if (Amp::isTemplate($node)) {+ // Ignore images inside templates.+ $node = $this->skipNodeAndChildren($node);+ } else {+ $node = $this->nextNode($node);+ }+ }++ // Optimize data-hero element if defined.+ if (count($heroImages) > 0) {+ return $heroImages;+ }++ // Fall back to auto-detected hero image if available.+ if ($heroImageCandidate) {+ return [$heroImageCandidate];+ }++ // No hero images to optimize.+ return [];+ }++ /**+ * Detect a hero image with the data-hero attribute.+ *+ * @param DOMElement $element Element to detect for.+ * @return HeroImage|null Detected hero image, or null if none detected.+ */+ private function detectImageWithDataHero(DOMElement $element)+ {+ if (+ $element->tagName === Extension::IMAGE+ && $element->hasAttribute(Attribute::DATA_HERO)+ ) {+ return new HeroImage(+ $element->getAttribute(Attribute::SRC),+ $element->getAttribute(Attribute::MEDIA),+ $element->getAttribute(Attribute::SRCSET),+ $element+ );+ }++ if (+ Amp::isAmpIframe($element)+ && $element->hasAttribute(Attribute::DATA_HERO)+ ) {+ return $this->getPlaceholderImage($element);+ }++ return null;+ }++ /**+ * Detect a hero image candidate.+ *+ * The hero image here can come from one of <amp-img>, <amp-video>, <amp-iframe>, <amp-video-iframe>.+ *+ * @param DOMElement $element Element to detect for.+ * @return HeroImage|null Detected hero image candidate, or null if none detected.+ */+ private function detectHeroImageCandidate(DOMElement $element)+ {+ if (+ $element->hasAttribute(Attribute::LAYOUT)+ && $element->getAttribute(Attribute::LAYOUT) === Layout::NODISPLAY+ ) {+ return null;+ }++ if ($element->tagName === Extension::IMAGE) {+ return $this->detectHeroImageCandidateForAmpImg($element);+ }++ if ($element->tagName === EXTENSION::VIDEO) {+ return $this->detectHeroImageCandidateForPosterImage($element);+ }++ if (Amp::isAmpIframe($element)) {+ return $this->detectHeroImageCandidateForIframePlaceholderImage($element);+ }++ return null;+ }++ /**+ * Detect a hero image candidate from an <amp-img> element.+ *+ * @param DOMElement $element Element to detect for.+ * @return HeroImage|null Detected hero image candidate, or null if none detected.+ */+ private function detectHeroImageCandidateForAmpImg(DOMElement $element)+ {+ $src = $element->getAttribute(Attribute::SRC);++ if (empty($src)) {+ return null;+ }++ if (! Url::isValidImageSrc($src)) {+ return null;+ }++ if ((new ImageDimensions($element))->isTiny()) {+ return null;+ }++ $srcset = $element->getAttribute(Attribute::SRCSET);+ $media = $element->getAttribute(Attribute::MEDIA);++ return new HeroImage($src, $media, $srcset, $element);+ }++ /**+ * Detect a hero image candidate from a video's poster (= placeholder) image.+ *+ * @param DOMElement $element Element to detect for.+ * @return HeroImage|null Detected hero image candidate, or null if none detected.+ */+ private function detectHeroImageCandidateForPosterImage(DOMElement $element)+ {+ $poster = $element->getAttribute(Attribute::POSTER);++ if (! $poster) {+ return null;+ }++ if (! Url::isValidImageSrc($poster)) {+ return null;+ }++ if ((new ImageDimensions($element))->isTiny()) {+ return null;+ }++ $media = $element->getAttribute(Attribute::MEDIA);++ return new HeroImage($poster, $media, '');+ }++ /**+ * Detect a hero image candidate from an iframe's placeholder image.+ *+ * @param DOMElement $element Element to detect for.+ * @return HeroImage|null Detected hero image candidate, or null if none detected.+ */+ private function detectHeroImageCandidateForIframePlaceholderImage(DOMElement $element)
private function detectHeroImageCandidateForPlaceholderImage(DOMElement $element)
comment created time in a day
Pull request review commentampproject/amp-wp
Add PreloadHeroImage Optimizer transformer
+<?php++namespace AmpProject\Optimizer\Transformer;++use AmpProject\Amp;+use AmpProject\Attribute;+use AmpProject\Dom\Document;+use AmpProject\Extension;+use AmpProject\Layout;+use AmpProject\Optimizer\Configuration\PreloadHeroImageConfiguration;+use AmpProject\Optimizer\Error;+use AmpProject\Optimizer\ErrorCollection;+use AmpProject\Optimizer\HeroImage;+use AmpProject\Optimizer\ImageDimensions;+use AmpProject\Optimizer\Transformer;+use AmpProject\Optimizer\TransformerConfiguration;+use AmpProject\Tag;+use AmpProject\Url;+use DOMElement;+use DOMNode;++/**+ * PreloadHeroImage - this transformer optimizes image rendering times for hero images. For hero images it will:+ *+ * 1. Inject a preload hint (if possible)+ * 2. Generate an img tag enabling the browser to render the image without the AMP runtime being loaded.+ *+ * Hero images are either identified automatically or can be explicitly defined by adding an `data-hero` attribute to+ * the element.+ *+ * This transformer supports the following options:+ *+ * * `preloadHeroImage`: [true|false] - enables or disables hero image preloading. The default is `true`.+ *+ * This is ported from the NodeJS optimizer.+ *+ * @version 3429af9d91e2c9efe1af85757499e5a308755f5f+ * @link https://github.com/ampproject/amp-toolbox/blob/3429af9d91e2c9efe1af85757499e5a308755f5f/packages/optimizer/lib/transformers/PreloadHeroImage.js+ *+ * @package ampproject/optimizer+ */+final class PreloadHeroImage implements Transformer+{++ /**+ * Class(es) to apply to a serverside-rendered image element.+ *+ * @var string+ */+ const SSR_IMAGE_CLASS = 'i-amphtml-fill-content i-amphtml-replaced-content';++ /**+ * List of attributes to copy onto an SSR'ed image.+ *+ * @var string[]+ */+ const ATTRIBUTES_TO_COPY = [+ Attribute::ALT,+ Attribute::ATTRIBUTION,+ Attribute::OBJECT_FIT,+ Attribute::OBJECT_POSITION,+ Attribute::REFERRERPOLICY,+ Attribute::SRC,+ Attribute::SRCSET,+ Attribute::SIZES,+ Attribute::TITLE,+ ];++ /**+ * Maximum number of hero images defined via data-hero attribute.+ *+ * @var int+ */+ const DATA_HERO_MAX = 2;++ /**+ * Configuration store to use.+ *+ * @var TransformerConfiguration+ */+ private $configuration;++ /**+ * Instantiate a PreloadHeroImage object.+ *+ * @param TransformerConfiguration $configuration Configuration store to use.+ */+ public function __construct(TransformerConfiguration $configuration)+ {+ $this->configuration = $configuration;+ }++ /**+ * Apply transformations to the provided DOM document.+ *+ * @param Document $document DOM document to apply the transformations to.+ * @param ErrorCollection $errors Collection of errors that are collected during transformation.+ * @return void+ */+ public function transform(Document $document, ErrorCollection $errors)+ {+ if ($this->configuration->get(PreloadHeroImageConfiguration::PRELOAD_HERO_IMAGE) === false) {+ return;+ }++ $heroImages = $this->findHeroImages($document);+ $referenceNode = $document->viewport;++ $heroImageCount = count($heroImages);+ if ($heroImageCount > self::DATA_HERO_MAX) {+ $errors->add(Error\TooManyHeroImages::whenPastMaximum());+ $heroImageCount = self::DATA_HERO_MAX;+ }++ $isAmpStory = Amp::isAmpStory($document);++ for ($index = 0; $index < $heroImageCount; $index++) {+ $this->generatePreload($heroImages[$index], $document, $errors, $referenceNode);+ $this->generateImg($heroImages[$index], $document);+ }+ }++ /**+ * Find the hero images to optimize.+ *+ * @param Document $document Document to look for hero images in.+ * @return HeroImage[] Array of hero images to optimize.+ */+ private function findHeroImages(Document $document)+ {+ $heroImageCandidate = null;+ $heroImages = [];+ $node = $document->body;++ while ($node !== null) {+ if (! $node instanceof DOMElement) {+ $node = $this->nextNode($node);+ continue;+ }++ $heroImage = $this->detectImageWithDataHero($node);+ if ($heroImage) {+ $heroImages[] = $heroImage;+ }++ if (! $heroImageCandidate && count($heroImages) === 0) {+ $heroImageCandidate = $this->detectHeroImageCandidate($node);+ }+ if (Amp::isTemplate($node)) {+ // Ignore images inside templates.+ $node = $this->skipNodeAndChildren($node);+ } else {+ $node = $this->nextNode($node);+ }+ }++ // Optimize data-hero element if defined.+ if (count($heroImages) > 0) {+ return $heroImages;+ }++ // Fall back to auto-detected hero image if available.+ if ($heroImageCandidate) {+ return [$heroImageCandidate];+ }++ // No hero images to optimize.+ return [];+ }++ /**+ * Detect a hero image with the data-hero attribute.+ *+ * @param DOMElement $element Element to detect for.+ * @return HeroImage|null Detected hero image, or null if none detected.+ */+ private function detectImageWithDataHero(DOMElement $element)+ {+ if (+ $element->tagName === Extension::IMAGE+ && $element->hasAttribute(Attribute::DATA_HERO)+ ) {+ return new HeroImage(+ $element->getAttribute(Attribute::SRC),+ $element->getAttribute(Attribute::MEDIA),+ $element->getAttribute(Attribute::SRCSET),+ $element+ );+ }++ if (+ Amp::isAmpIframe($element)+ && $element->hasAttribute(Attribute::DATA_HERO)+ ) {+ return $this->getPlaceholderImage($element);+ }++ return null;+ }++ /**+ * Detect a hero image candidate.+ *+ * The hero image here can come from one of <amp-img>, <amp-video>, <amp-iframe>, <amp-video-iframe>.+ *+ * @param DOMElement $element Element to detect for.+ * @return HeroImage|null Detected hero image candidate, or null if none detected.+ */+ private function detectHeroImageCandidate(DOMElement $element)+ {+ if (+ $element->hasAttribute(Attribute::LAYOUT)+ && $element->getAttribute(Attribute::LAYOUT) === Layout::NODISPLAY+ ) {+ return null;+ }++ if ($element->tagName === Extension::IMAGE) {+ return $this->detectHeroImageCandidateForAmpImg($element);+ }++ if ($element->tagName === EXTENSION::VIDEO) {+ return $this->detectHeroImageCandidateForPosterImage($element);+ }++ if (Amp::isAmpIframe($element)) {
This condition can be expanded to include all embeds, including amp-youtube, amp-vimeo, etc.
comment created time in a day
Pull request review commentampproject/amp-wp
Add PreloadHeroImage Optimizer transformer
+<?php++namespace AmpProject\Optimizer\Transformer;++use AmpProject\Amp;+use AmpProject\Attribute;+use AmpProject\Dom\Document;+use AmpProject\Extension;+use AmpProject\Layout;+use AmpProject\Optimizer\Configuration\PreloadHeroImageConfiguration;+use AmpProject\Optimizer\Error;+use AmpProject\Optimizer\ErrorCollection;+use AmpProject\Optimizer\HeroImage;+use AmpProject\Optimizer\ImageDimensions;+use AmpProject\Optimizer\Transformer;+use AmpProject\Optimizer\TransformerConfiguration;+use AmpProject\Tag;+use AmpProject\Url;+use DOMElement;+use DOMNode;++/**+ * PreloadHeroImage - this transformer optimizes image rendering times for hero images. For hero images it will:+ *+ * 1. Inject a preload hint (if possible)+ * 2. Generate an img tag enabling the browser to render the image without the AMP runtime being loaded.+ *+ * Hero images are either identified automatically or can be explicitly defined by adding an `data-hero` attribute to+ * the element.+ *+ * This transformer supports the following options:+ *+ * * `preloadHeroImage`: [true|false] - enables or disables hero image preloading. The default is `true`.+ *+ * This is ported from the NodeJS optimizer.+ *+ * @version 3429af9d91e2c9efe1af85757499e5a308755f5f+ * @link https://github.com/ampproject/amp-toolbox/blob/3429af9d91e2c9efe1af85757499e5a308755f5f/packages/optimizer/lib/transformers/PreloadHeroImage.js+ *+ * @package ampproject/optimizer+ */+final class PreloadHeroImage implements Transformer+{++ /**+ * Class(es) to apply to a serverside-rendered image element.+ *+ * @var string+ */+ const SSR_IMAGE_CLASS = 'i-amphtml-fill-content i-amphtml-replaced-content';++ /**+ * List of attributes to copy onto an SSR'ed image.+ *+ * @var string[]+ */+ const ATTRIBUTES_TO_COPY = [+ Attribute::ALT,+ Attribute::ATTRIBUTION,+ Attribute::OBJECT_FIT,+ Attribute::OBJECT_POSITION,+ Attribute::REFERRERPOLICY,+ Attribute::SRC,+ Attribute::SRCSET,+ Attribute::SIZES,+ Attribute::TITLE,+ ];++ /**+ * Maximum number of hero images defined via data-hero attribute.+ *+ * @var int+ */+ const DATA_HERO_MAX = 2;++ /**+ * Configuration store to use.+ *+ * @var TransformerConfiguration+ */+ private $configuration;++ /**+ * Instantiate a PreloadHeroImage object.+ *+ * @param TransformerConfiguration $configuration Configuration store to use.+ */+ public function __construct(TransformerConfiguration $configuration)+ {+ $this->configuration = $configuration;+ }++ /**+ * Apply transformations to the provided DOM document.+ *+ * @param Document $document DOM document to apply the transformations to.+ * @param ErrorCollection $errors Collection of errors that are collected during transformation.+ * @return void+ */+ public function transform(Document $document, ErrorCollection $errors)+ {+ if ($this->configuration->get(PreloadHeroImageConfiguration::PRELOAD_HERO_IMAGE) === false) {+ return;+ }++ $heroImages = $this->findHeroImages($document);+ $referenceNode = $document->viewport;++ $heroImageCount = count($heroImages);+ if ($heroImageCount > self::DATA_HERO_MAX) {+ $errors->add(Error\TooManyHeroImages::whenPastMaximum());+ $heroImageCount = self::DATA_HERO_MAX;+ }++ $isAmpStory = Amp::isAmpStory($document);++ for ($index = 0; $index < $heroImageCount; $index++) {+ $this->generatePreload($heroImages[$index], $document, $errors, $referenceNode);+ $this->generateImg($heroImages[$index], $document);+ }+ }++ /**+ * Find the hero images to optimize.+ *+ * @param Document $document Document to look for hero images in.+ * @return HeroImage[] Array of hero images to optimize.+ */+ private function findHeroImages(Document $document)+ {+ $heroImageCandidate = null;+ $heroImages = [];+ $node = $document->body;++ while ($node !== null) {+ if (! $node instanceof DOMElement) {+ $node = $this->nextNode($node);+ continue;+ }++ $heroImage = $this->detectImageWithDataHero($node);+ if ($heroImage) {+ $heroImages[] = $heroImage;+ }++ if (! $heroImageCandidate && count($heroImages) === 0) {+ $heroImageCandidate = $this->detectHeroImageCandidate($node);+ }+ if (Amp::isTemplate($node)) {+ // Ignore images inside templates.+ $node = $this->skipNodeAndChildren($node);+ } else {+ $node = $this->nextNode($node);+ }+ }++ // Optimize data-hero element if defined.+ if (count($heroImages) > 0) {+ return $heroImages;+ }++ // Fall back to auto-detected hero image if available.+ if ($heroImageCandidate) {+ return [$heroImageCandidate];+ }++ // No hero images to optimize.+ return [];+ }++ /**+ * Detect a hero image with the data-hero attribute.+ *+ * @param DOMElement $element Element to detect for.+ * @return HeroImage|null Detected hero image, or null if none detected.+ */+ private function detectImageWithDataHero(DOMElement $element)+ {+ if (+ $element->tagName === Extension::IMAGE+ && $element->hasAttribute(Attribute::DATA_HERO)+ ) {+ return new HeroImage(+ $element->getAttribute(Attribute::SRC),+ $element->getAttribute(Attribute::MEDIA),+ $element->getAttribute(Attribute::SRCSET),+ $element+ );+ }++ if (+ Amp::isAmpIframe($element)+ && $element->hasAttribute(Attribute::DATA_HERO)+ ) {+ return $this->getPlaceholderImage($element);+ }++ return null;+ }++ /**+ * Detect a hero image candidate.+ *+ * The hero image here can come from one of <amp-img>, <amp-video>, <amp-iframe>, <amp-video-iframe>.+ *+ * @param DOMElement $element Element to detect for.+ * @return HeroImage|null Detected hero image candidate, or null if none detected.+ */+ private function detectHeroImageCandidate(DOMElement $element)+ {+ if (+ $element->hasAttribute(Attribute::LAYOUT)+ && $element->getAttribute(Attribute::LAYOUT) === Layout::NODISPLAY+ ) {+ return null;+ }++ if ($element->tagName === Extension::IMAGE) {+ return $this->detectHeroImageCandidateForAmpImg($element);+ }++ if ($element->tagName === EXTENSION::VIDEO) {+ return $this->detectHeroImageCandidateForPosterImage($element);+ }++ if (Amp::isAmpIframe($element)) {+ return $this->detectHeroImageCandidateForIframePlaceholderImage($element);+ }++ return null;+ }++ /**+ * Detect a hero image candidate from an <amp-img> element.+ *+ * @param DOMElement $element Element to detect for.+ * @return HeroImage|null Detected hero image candidate, or null if none detected.+ */+ private function detectHeroImageCandidateForAmpImg(DOMElement $element)+ {+ $src = $element->getAttribute(Attribute::SRC);++ if (empty($src)) {+ return null;+ }++ if (! Url::isValidImageSrc($src)) {+ return null;+ }++ if ((new ImageDimensions($element))->isTiny()) {+ return null;+ }++ $srcset = $element->getAttribute(Attribute::SRCSET);+ $media = $element->getAttribute(Attribute::MEDIA);++ return new HeroImage($src, $media, $srcset, $element);+ }++ /**+ * Detect a hero image candidate from a video's poster (= placeholder) image.+ *+ * @param DOMElement $element Element to detect for.+ * @return HeroImage|null Detected hero image candidate, or null if none detected.+ */+ private function detectHeroImageCandidateForPosterImage(DOMElement $element)+ {+ $poster = $element->getAttribute(Attribute::POSTER);++ if (! $poster) {+ return null;+ }++ if (! Url::isValidImageSrc($poster)) {+ return null;+ }++ if ((new ImageDimensions($element))->isTiny()) {+ return null;+ }++ $media = $element->getAttribute(Attribute::MEDIA);++ return new HeroImage($poster, $media, '');+ }++ /**+ * Detect a hero image candidate from an iframe's placeholder image.+ *+ * @param DOMElement $element Element to detect for.+ * @return HeroImage|null Detected hero image candidate, or null if none detected.+ */+ private function detectHeroImageCandidateForIframePlaceholderImage(DOMElement $element)+ {+ // A placeholder <amp-img> is required to preload an image for an iframe.+ if (! $element->hasChildNodes()) {+ return null;+ }++ if ((new ImageDimensions($element))->isTiny()) {+ return null;+ }++ return $this->getPlaceholderImage($element);+ }++ /**+ * Get the placeholder image for a given element.+ *+ * @param DOMElement $element Element to check the placeholder image for.+ * @return HeroImage|null Placeholder image to use or null if none found.+ */+ private function getPlaceholderImage(DOMElement $element)+ {+ foreach ($element->childNodes as $childNode) {+ if (+ ! $childNode instanceof DOMElement+ || $childNode->tagName !== Extension::IMAGE+ || ! $childNode->hasAttribute(Attribute::PLACEHOLDER)+ ) {+ continue;+ }+
Some new logic can be added here to see if $childNode->tagName === Extension::IMAGE, and if so, use its $src. Otherwise, query $childNode for the first descendant Extension::IMAGE and use it instead.
comment created time in a day
Pull request review commentampproject/amp-wp
Add PreloadHeroImage Optimizer transformer
+<?php++namespace AmpProject\Optimizer\Transformer;++use AmpProject\Amp;+use AmpProject\Attribute;+use AmpProject\Dom\Document;+use AmpProject\Extension;+use AmpProject\Layout;+use AmpProject\Optimizer\Configuration\PreloadHeroImageConfiguration;+use AmpProject\Optimizer\Error;+use AmpProject\Optimizer\ErrorCollection;+use AmpProject\Optimizer\HeroImage;+use AmpProject\Optimizer\ImageDimensions;+use AmpProject\Optimizer\Transformer;+use AmpProject\Optimizer\TransformerConfiguration;+use AmpProject\Tag;+use AmpProject\Url;+use DOMElement;+use DOMNode;++/**+ * PreloadHeroImage - this transformer optimizes image rendering times for hero images. For hero images it will:+ *+ * 1. Inject a preload hint (if possible)+ * 2. Generate an img tag enabling the browser to render the image without the AMP runtime being loaded.+ *+ * Hero images are either identified automatically or can be explicitly defined by adding an `data-hero` attribute to+ * the element.+ *+ * This transformer supports the following options:+ *+ * * `preloadHeroImage`: [true|false] - enables or disables hero image preloading. The default is `true`.+ *+ * This is ported from the NodeJS optimizer.+ *+ * @version 3429af9d91e2c9efe1af85757499e5a308755f5f+ * @link https://github.com/ampproject/amp-toolbox/blob/3429af9d91e2c9efe1af85757499e5a308755f5f/packages/optimizer/lib/transformers/PreloadHeroImage.js+ *+ * @package ampproject/optimizer+ */+final class PreloadHeroImage implements Transformer+{++ /**+ * Class(es) to apply to a serverside-rendered image element.+ *+ * @var string+ */+ const SSR_IMAGE_CLASS = 'i-amphtml-fill-content i-amphtml-replaced-content';++ /**+ * List of attributes to copy onto an SSR'ed image.+ *+ * @var string[]+ */+ const ATTRIBUTES_TO_COPY = [+ Attribute::ALT,+ Attribute::ATTRIBUTION,+ Attribute::OBJECT_FIT,+ Attribute::OBJECT_POSITION,+ Attribute::REFERRERPOLICY,+ Attribute::SRC,+ Attribute::SRCSET,+ Attribute::SIZES,+ Attribute::TITLE,+ ];++ /**+ * Maximum number of hero images defined via data-hero attribute.+ *+ * @var int+ */+ const DATA_HERO_MAX = 2;++ /**+ * Configuration store to use.+ *+ * @var TransformerConfiguration+ */+ private $configuration;++ /**+ * Instantiate a PreloadHeroImage object.+ *+ * @param TransformerConfiguration $configuration Configuration store to use.+ */+ public function __construct(TransformerConfiguration $configuration)+ {+ $this->configuration = $configuration;+ }++ /**+ * Apply transformations to the provided DOM document.+ *+ * @param Document $document DOM document to apply the transformations to.+ * @param ErrorCollection $errors Collection of errors that are collected during transformation.+ * @return void+ */+ public function transform(Document $document, ErrorCollection $errors)+ {+ if ($this->configuration->get(PreloadHeroImageConfiguration::PRELOAD_HERO_IMAGE) === false) {+ return;+ }++ $heroImages = $this->findHeroImages($document);+ $referenceNode = $document->viewport;++ $heroImageCount = count($heroImages);+ if ($heroImageCount > self::DATA_HERO_MAX) {+ $errors->add(Error\TooManyHeroImages::whenPastMaximum());+ $heroImageCount = self::DATA_HERO_MAX;+ }++ $isAmpStory = Amp::isAmpStory($document);++ for ($index = 0; $index < $heroImageCount; $index++) {+ $this->generatePreload($heroImages[$index], $document, $errors, $referenceNode);+ $this->generateImg($heroImages[$index], $document);+ }+ }++ /**+ * Find the hero images to optimize.+ *+ * @param Document $document Document to look for hero images in.+ * @return HeroImage[] Array of hero images to optimize.+ */+ private function findHeroImages(Document $document)+ {+ $heroImageCandidate = null;+ $heroImages = [];+ $node = $document->body;++ while ($node !== null) {+ if (! $node instanceof DOMElement) {+ $node = $this->nextNode($node);+ continue;+ }++ $heroImage = $this->detectImageWithDataHero($node);+ if ($heroImage) {+ $heroImages[] = $heroImage;+ }++ if (! $heroImageCandidate && count($heroImages) === 0) {+ $heroImageCandidate = $this->detectHeroImageCandidate($node);+ }+ if (Amp::isTemplate($node)) {+ // Ignore images inside templates.+ $node = $this->skipNodeAndChildren($node);+ } else {+ $node = $this->nextNode($node);+ }+ }++ // Optimize data-hero element if defined.+ if (count($heroImages) > 0) {+ return $heroImages;+ }++ // Fall back to auto-detected hero image if available.+ if ($heroImageCandidate) {+ return [$heroImageCandidate];+ }++ // No hero images to optimize.+ return [];+ }++ /**+ * Detect a hero image with the data-hero attribute.+ *+ * @param DOMElement $element Element to detect for.+ * @return HeroImage|null Detected hero image, or null if none detected.+ */+ private function detectImageWithDataHero(DOMElement $element)+ {+ if (+ $element->tagName === Extension::IMAGE+ && $element->hasAttribute(Attribute::DATA_HERO)+ ) {+ return new HeroImage(+ $element->getAttribute(Attribute::SRC),+ $element->getAttribute(Attribute::MEDIA),+ $element->getAttribute(Attribute::SRCSET),+ $element+ );+ }++ if (+ Amp::isAmpIframe($element)+ && $element->hasAttribute(Attribute::DATA_HERO)+ ) {+ return $this->getPlaceholderImage($element);+ }++ return null;+ }++ /**+ * Detect a hero image candidate.+ *+ * The hero image here can come from one of <amp-img>, <amp-video>, <amp-iframe>, <amp-video-iframe>.+ *+ * @param DOMElement $element Element to detect for.+ * @return HeroImage|null Detected hero image candidate, or null if none detected.+ */+ private function detectHeroImageCandidate(DOMElement $element)+ {+ if (+ $element->hasAttribute(Attribute::LAYOUT)+ && $element->getAttribute(Attribute::LAYOUT) === Layout::NODISPLAY+ ) {+ return null;+ }++ if ($element->tagName === Extension::IMAGE) {+ return $this->detectHeroImageCandidateForAmpImg($element);+ }++ if ($element->tagName === EXTENSION::VIDEO) {+ return $this->detectHeroImageCandidateForPosterImage($element);+ }++ if (Amp::isAmpIframe($element)) {+ return $this->detectHeroImageCandidateForIframePlaceholderImage($element);+ }++ return null;+ }++ /**+ * Detect a hero image candidate from an <amp-img> element.+ *+ * @param DOMElement $element Element to detect for.+ * @return HeroImage|null Detected hero image candidate, or null if none detected.+ */+ private function detectHeroImageCandidateForAmpImg(DOMElement $element)+ {+ $src = $element->getAttribute(Attribute::SRC);++ if (empty($src)) {+ return null;+ }++ if (! Url::isValidImageSrc($src)) {+ return null;+ }++ if ((new ImageDimensions($element))->isTiny()) {+ return null;+ }++ $srcset = $element->getAttribute(Attribute::SRCSET);+ $media = $element->getAttribute(Attribute::MEDIA);++ return new HeroImage($src, $media, $srcset, $element);+ }++ /**+ * Detect a hero image candidate from a video's poster (= placeholder) image.+ *+ * @param DOMElement $element Element to detect for.+ * @return HeroImage|null Detected hero image candidate, or null if none detected.+ */+ private function detectHeroImageCandidateForPosterImage(DOMElement $element)+ {+ $poster = $element->getAttribute(Attribute::POSTER);++ if (! $poster) {+ return null;+ }++ if (! Url::isValidImageSrc($poster)) {+ return null;+ }++ if ((new ImageDimensions($element))->isTiny()) {+ return null;+ }++ $media = $element->getAttribute(Attribute::MEDIA);++ return new HeroImage($poster, $media, '');+ }++ /**+ * Detect a hero image candidate from an iframe's placeholder image.+ *+ * @param DOMElement $element Element to detect for.+ * @return HeroImage|null Detected hero image candidate, or null if none detected.+ */+ private function detectHeroImageCandidateForIframePlaceholderImage(DOMElement $element)+ {+ // A placeholder <amp-img> is required to preload an image for an iframe.+ if (! $element->hasChildNodes()) {+ return null;+ }++ if ((new ImageDimensions($element))->isTiny()) {+ return null;+ }++ return $this->getPlaceholderImage($element);+ }++ /**+ * Get the placeholder image for a given element.+ *+ * @param DOMElement $element Element to check the placeholder image for.+ * @return HeroImage|null Placeholder image to use or null if none found.+ */+ private function getPlaceholderImage(DOMElement $element)+ {+ foreach ($element->childNodes as $childNode) {+ if (+ ! $childNode instanceof DOMElement+ || $childNode->tagName !== Extension::IMAGE+ || ! $childNode->hasAttribute(Attribute::PLACEHOLDER)+ ) {+ continue;+ }+
Nevertheless, should it be checking for amp-anim in addition to amp-img?
comment created time in a day
Pull request review commentampproject/amp-wp
Add PreloadHeroImage Optimizer transformer
+<?php++namespace AmpProject\Optimizer\Transformer;++use AmpProject\Amp;+use AmpProject\Attribute;+use AmpProject\Dom\Document;+use AmpProject\Extension;+use AmpProject\Layout;+use AmpProject\Optimizer\Configuration\PreloadHeroImageConfiguration;+use AmpProject\Optimizer\Error;+use AmpProject\Optimizer\ErrorCollection;+use AmpProject\Optimizer\HeroImage;+use AmpProject\Optimizer\ImageDimensions;+use AmpProject\Optimizer\Transformer;+use AmpProject\Optimizer\TransformerConfiguration;+use AmpProject\Tag;+use AmpProject\Url;+use DOMElement;+use DOMNode;++/**+ * PreloadHeroImage - this transformer optimizes image rendering times for hero images. For hero images it will:+ *+ * 1. Inject a preload hint (if possible)+ * 2. Generate an img tag enabling the browser to render the image without the AMP runtime being loaded.+ *+ * Hero images are either identified automatically or can be explicitly defined by adding an `data-hero` attribute to+ * the element.+ *+ * This transformer supports the following options:+ *+ * * `preloadHeroImage`: [true|false] - enables or disables hero image preloading. The default is `true`.+ *+ * This is ported from the NodeJS optimizer.+ *+ * @version 3429af9d91e2c9efe1af85757499e5a308755f5f+ * @link https://github.com/ampproject/amp-toolbox/blob/3429af9d91e2c9efe1af85757499e5a308755f5f/packages/optimizer/lib/transformers/PreloadHeroImage.js+ *+ * @package ampproject/optimizer+ */+final class PreloadHeroImage implements Transformer+{++ /**+ * Class(es) to apply to a serverside-rendered image element.+ *+ * @var string+ */+ const SSR_IMAGE_CLASS = 'i-amphtml-fill-content i-amphtml-replaced-content';++ /**+ * List of attributes to copy onto an SSR'ed image.+ *+ * @var string[]+ */+ const ATTRIBUTES_TO_COPY = [+ Attribute::ALT,+ Attribute::ATTRIBUTION,+ Attribute::OBJECT_FIT,+ Attribute::OBJECT_POSITION,+ Attribute::REFERRERPOLICY,+ Attribute::SRC,+ Attribute::SRCSET,+ Attribute::SIZES,+ Attribute::TITLE,+ ];++ /**+ * Maximum number of hero images defined via data-hero attribute.+ *+ * @var int+ */+ const DATA_HERO_MAX = 2;++ /**+ * Configuration store to use.+ *+ * @var TransformerConfiguration+ */+ private $configuration;++ /**+ * Instantiate a PreloadHeroImage object.+ *+ * @param TransformerConfiguration $configuration Configuration store to use.+ */+ public function __construct(TransformerConfiguration $configuration)+ {+ $this->configuration = $configuration;+ }++ /**+ * Apply transformations to the provided DOM document.+ *+ * @param Document $document DOM document to apply the transformations to.+ * @param ErrorCollection $errors Collection of errors that are collected during transformation.+ * @return void+ */+ public function transform(Document $document, ErrorCollection $errors)+ {+ if ($this->configuration->get(PreloadHeroImageConfiguration::PRELOAD_HERO_IMAGE) === false) {+ return;+ }++ $heroImages = $this->findHeroImages($document);+ $referenceNode = $document->viewport;++ $heroImageCount = count($heroImages);+ if ($heroImageCount > self::DATA_HERO_MAX) {+ $errors->add(Error\TooManyHeroImages::whenPastMaximum());+ $heroImageCount = self::DATA_HERO_MAX;+ }++ $isAmpStory = Amp::isAmpStory($document);++ for ($index = 0; $index < $heroImageCount; $index++) {+ $this->generatePreload($heroImages[$index], $document, $errors, $referenceNode);+ $this->generateImg($heroImages[$index], $document);+ }+ }++ /**+ * Find the hero images to optimize.+ *+ * @param Document $document Document to look for hero images in.+ * @return HeroImage[] Array of hero images to optimize.+ */+ private function findHeroImages(Document $document)+ {+ $heroImageCandidate = null;+ $heroImages = [];+ $node = $document->body;++ while ($node !== null) {+ if (! $node instanceof DOMElement) {+ $node = $this->nextNode($node);+ continue;+ }++ $heroImage = $this->detectImageWithDataHero($node);+ if ($heroImage) {+ $heroImages[] = $heroImage;+ }++ if (! $heroImageCandidate && count($heroImages) === 0) {+ $heroImageCandidate = $this->detectHeroImageCandidate($node);+ }+ if (Amp::isTemplate($node)) {+ // Ignore images inside templates.+ $node = $this->skipNodeAndChildren($node);+ } else {+ $node = $this->nextNode($node);+ }+ }++ // Optimize data-hero element if defined.+ if (count($heroImages) > 0) {+ return $heroImages;+ }++ // Fall back to auto-detected hero image if available.+ if ($heroImageCandidate) {+ return [$heroImageCandidate];+ }++ // No hero images to optimize.+ return [];+ }++ /**+ * Detect a hero image with the data-hero attribute.+ *+ * @param DOMElement $element Element to detect for.+ * @return HeroImage|null Detected hero image, or null if none detected.+ */+ private function detectImageWithDataHero(DOMElement $element)+ {+ if (+ $element->tagName === Extension::IMAGE+ && $element->hasAttribute(Attribute::DATA_HERO)+ ) {+ return new HeroImage(+ $element->getAttribute(Attribute::SRC),+ $element->getAttribute(Attribute::MEDIA),+ $element->getAttribute(Attribute::SRCSET),+ $element+ );+ }++ if (+ Amp::isAmpIframe($element)+ && $element->hasAttribute(Attribute::DATA_HERO)+ ) {+ return $this->getPlaceholderImage($element);+ }++ return null;+ }++ /**+ * Detect a hero image candidate.+ *+ * The hero image here can come from one of <amp-img>, <amp-video>, <amp-iframe>, <amp-video-iframe>.+ *+ * @param DOMElement $element Element to detect for.+ * @return HeroImage|null Detected hero image candidate, or null if none detected.+ */+ private function detectHeroImageCandidate(DOMElement $element)+ {+ if (+ $element->hasAttribute(Attribute::LAYOUT)+ && $element->getAttribute(Attribute::LAYOUT) === Layout::NODISPLAY+ ) {+ return null;+ }++ if ($element->tagName === Extension::IMAGE) {+ return $this->detectHeroImageCandidateForAmpImg($element);+ }++ if ($element->tagName === EXTENSION::VIDEO) {+ return $this->detectHeroImageCandidateForPosterImage($element);+ }++ if (Amp::isAmpIframe($element)) {+ return $this->detectHeroImageCandidateForIframePlaceholderImage($element);+ }++ return null;+ }++ /**+ * Detect a hero image candidate from an <amp-img> element.+ *+ * @param DOMElement $element Element to detect for.+ * @return HeroImage|null Detected hero image candidate, or null if none detected.+ */+ private function detectHeroImageCandidateForAmpImg(DOMElement $element)+ {+ $src = $element->getAttribute(Attribute::SRC);++ if (empty($src)) {+ return null;+ }++ if (! Url::isValidImageSrc($src)) {+ return null;+ }++ if ((new ImageDimensions($element))->isTiny()) {+ return null;+ }++ $srcset = $element->getAttribute(Attribute::SRCSET);+ $media = $element->getAttribute(Attribute::MEDIA);++ return new HeroImage($src, $media, $srcset, $element);+ }++ /**+ * Detect a hero image candidate from a video's poster (= placeholder) image.+ *+ * @param DOMElement $element Element to detect for.+ * @return HeroImage|null Detected hero image candidate, or null if none detected.+ */+ private function detectHeroImageCandidateForPosterImage(DOMElement $element)+ {+ $poster = $element->getAttribute(Attribute::POSTER);++ if (! $poster) {+ return null;+ }++ if (! Url::isValidImageSrc($poster)) {+ return null;+ }++ if ((new ImageDimensions($element))->isTiny()) {+ return null;+ }++ $media = $element->getAttribute(Attribute::MEDIA);++ return new HeroImage($poster, $media, '');+ }++ /**+ * Detect a hero image candidate from an iframe's placeholder image.+ *+ * @param DOMElement $element Element to detect for.+ * @return HeroImage|null Detected hero image candidate, or null if none detected.+ */+ private function detectHeroImageCandidateForIframePlaceholderImage(DOMElement $element)+ {+ // A placeholder <amp-img> is required to preload an image for an iframe.+ if (! $element->hasChildNodes()) {+ return null;+ }++ if ((new ImageDimensions($element))->isTiny()) {+ return null;+ }++ return $this->getPlaceholderImage($element);+ }++ /**+ * Get the placeholder image for a given element.+ *+ * @param DOMElement $element Element to check the placeholder image for.+ * @return HeroImage|null Placeholder image to use or null if none found.+ */+ private function getPlaceholderImage(DOMElement $element)+ {+ foreach ($element->childNodes as $childNode) {+ if (+ ! $childNode instanceof DOMElement+ || $childNode->tagName !== Extension::IMAGE
comment created time in a day
Pull request review commentampproject/amp-wp
Add PreloadHeroImage Optimizer transformer
+<?php++namespace AmpProject\Optimizer\Transformer;++use AmpProject\Amp;+use AmpProject\Attribute;+use AmpProject\Dom\Document;+use AmpProject\Extension;+use AmpProject\Layout;+use AmpProject\Optimizer\Configuration\PreloadHeroImageConfiguration;+use AmpProject\Optimizer\Error;+use AmpProject\Optimizer\ErrorCollection;+use AmpProject\Optimizer\HeroImage;+use AmpProject\Optimizer\Transformer;+use AmpProject\Optimizer\TransformerConfiguration;+use AmpProject\Tag;+use AmpProject\Url;+use DOMElement;+use DOMNode;++/**+ * PreloadHeroImage - this transformers optimizes image rendering times for hero images. For hero images it will:+ *+ * 1. Inject a preload hint (if possible)+ * 2. Generate an img tag enabling the browser to render the image without the AMP runtime being loaded.+ *+ * Hero images are either identified automatically or can be explicitly defined by adding an `data-hero` attribute to+ * the element.+ *+ * This transformer supports the following options:+ *+ * * `preloadHeroImage`: [true|false] - enables or disables hero image preloading. The default is `true`.+ *+ * This is ported from the NodeJS optimizer.+ *+ * @version 3429af9d91e2c9efe1af85757499e5a308755f5f+ * @link https://github.com/ampproject/amp-toolbox/blob/3429af9d91e2c9efe1af85757499e5a308755f5f/packages/optimizer/lib/transformers/PreloadHeroImage.js+ *+ * @package ampproject/optimizer+ */+final class PreloadHeroImage implements Transformer+{++ /**+ * Class(es) to apply to a serverside-rendered image element.+ *+ * @var string+ */+ const SSR_IMAGE_CLASS = 'i-amphtml-fill-content i-amphtml-replaced-content';++ /**+ * List of attributes to copy onto an SSR'ed image.+ *+ * @var string[]+ */+ const ATTRIBUTES_TO_COPY = [+ Attribute::ALT,+ Attribute::ATTRIBUTION,+ Attribute::OBJECT_FIT,+ Attribute::OBJECT_POSITION,+ Attribute::REFERRERPOLICY,+ Attribute::SRC,+ Attribute::SRCSET,+ Attribute::SIZES,+ Attribute::TITLE,+ ];++ /**+ * Images smaller than 150px are considered tiny.+ *+ * @var int+ */+ const TINY_IMG_THRESHOLD = 150;++ /**+ * Maximum number of hero images defined via data-hero attribute.+ *+ * @var int+ */+ const DATA_HERO_MAX = 2;++ /**+ * Configuration store to use.+ *+ * @var TransformerConfiguration+ */+ private $configuration;++ /**+ * Instantiate a PreloadHeroImage object.+ *+ * @param TransformerConfiguration $configuration Configuration store to use.+ */+ public function __construct(TransformerConfiguration $configuration)+ {+ $this->configuration = $configuration;+ }++ /**+ * Apply transformations to the provided DOM document.+ *+ * @param Document $document DOM document to apply the transformations to.+ * @param ErrorCollection $errors Collection of errors that are collected during transformation.+ * @return void+ */+ public function transform(Document $document, ErrorCollection $errors)+ {+ if ($this->configuration->get(PreloadHeroImageConfiguration::PRELOAD_HERO_IMAGE) === false) {+ return;+ }++ $heroImages = $this->findHeroImages($document);+ $referenceNode = $document->viewport;++ $heroImageCount = count($heroImages);+ if ($heroImageCount > self::DATA_HERO_MAX) {+ $errors->add(Error\TooManyHeroImages::whenPastMaximum());+ $heroImageCount = self::DATA_HERO_MAX;+ }++ $isAmpStory = Amp::isAmpStory($document);++ for ($index = 0; $index < $heroImageCount; $index++) {+ $this->generatePreload($heroImages[$index], $document, $errors, $referenceNode);+ if (! $isAmpStory) {+ // AMP Stories don't support SSR'd <amp-img> yet.+ // See https://github.com/ampproject/amphtml/issues/29850.+ $this->generateImg($heroImages[$index], $document);+ }+ }+ }++ /**+ * Find the hero images to optimize.+ *+ * @param Document $document Document to look for hero images in.+ * @return HeroImage[] Array of hero images to optimize.+ */+ private function findHeroImages(Document $document)+ {+ $heroImageCandidate = null;+ $heroImages = [];+ $node = $document->body;++ while ($node !== null) {+ if (! $node instanceof DOMElement) {+ $node = $this->nextNode($node);+ continue;+ }++ $heroImage = $this->detectImageWithDataHero($node);+ if ($heroImage) {+ $heroImages[] = $heroImage;+ }++ if (! $heroImageCandidate && count($heroImages) === 0) {+ $heroImageCandidate = $this->detectHeroImageCandidate($node);+ }+ if (Amp::isTemplate($node)) {+ // Ignore images inside templates.+ $node = $this->skipNodeAndChildren($node);+ } else {+ $node = $this->nextNode($node);+ }+ }++ // Optimize data-hero element if defined.+ if (count($heroImages) > 0) {+ return $heroImages;+ }++ // Fall back to auto-detected hero image if available.+ if ($heroImageCandidate) {+ return [$heroImageCandidate];+ }++ // No hero images to optimize.+ return [];+ }++ /**+ * Detect a hero image with the data-hero attribute.+ *+ * @param DOMElement $element Element to detect for.+ * @return HeroImage|null Detected hero image, or null if none detected.+ */+ private function detectImageWithDataHero(DOMElement $element)+ {+ if (+ $element->tagName === Extension::IMAGE+ && $element->hasAttribute(Attribute::DATA_HERO)+ ) {+ return new HeroImage(+ $element->getAttribute(Attribute::SRC),+ $element->getAttribute(Attribute::MEDIA),+ $element->getAttribute(Attribute::SRCSET),+ $element+ );+ }++ if (+ Amp::isAmpIframe($element)+ && $element->hasAttribute(Attribute::DATA_HERO)+ ) {+ return $this->getPlaceholderImage($element);+ }++ return null;+ }++ /**+ * Detect a hero image candidate.+ *+ * The hero image here can come from one of <amp-img>, <amp-video>, <amp-iframe>, <amp-video-iframe>.+ *+ * @param DOMElement $element Element to detect for.+ * @return HeroImage|null Detected hero image candidate, or null if none detected.+ */+ private function detectHeroImageCandidate(DOMElement $element)+ {+ if (+ $element->hasAttribute(Attribute::LAYOUT)+ && $element->getAttribute(Attribute::LAYOUT) === Layout::NODISPLAY+ ) {+ return null;+ }++ if ($element->tagName === Extension::IMAGE) {+ return $this->detectHeroImageCandidateForAmpImg($element);+ }++ if ($element->tagName === EXTENSION::VIDEO) {+ return $this->detectHeroImageCandidateForPosterImage($element);+ }++ if (Amp::isAmpIframe($element)) {+ return $this->detectHeroImageCandidateForIframePlaceholderImage($element);+ }
Apparently to support this, the detectHeroImageCandidateForIframePlaceholderImage method can just be renamed to detectHeroImageCandidateForPlaceholderImage, and instead of looking for direct descendants of the element for image placeholders, it should look for a placeholder direct descendant and then check if either it is an amp-img or it has an amp-img as a descendant (as in the case of a placeholder link having an image inside).
comment created time in a day
push eventampproject/amp-wp
commit sha aab68318aa0c39105cc17b8a56132c4ac43f7fcc
Update dependency postcss to v8.0.8
commit sha 95e1cd17a4b003b0a509e52cfa98bb60319d00f1
Merge pull request #5417 from renovate-bot/renovate/postcss-8.x Update dependency postcss to v8.0.8
push time in a day
PR merged ampproject/amp-wp
This PR contains the following updates:
| Package | Type | Update | Change |
|---|---|---|---|
| postcss (source) | devDependencies | patch | 8.0.7 -> 8.0.8 |
Release Notes
<details> <summary>postcss/postcss</summary>
v8.0.8
- Fix
8.0.7regression on PostCSS 7 nodes converting (by Adam Wathan).
</details>
Renovate configuration
:date: Schedule: At any time (no schedule defined).
:vertical_traffic_light: Automerge: Disabled by config. Please merge this manually once you are satisfied.
:recycle: Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
:no_bell: Ignore: Close this PR and you won't be reminded about this update again.
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box
This PR has been generated by WhiteSource Renovate. View repository job log here.
pr closed time in a day
push eventampproject/amp-wp
commit sha 16d2a7164821ae0990660f44f36655adc3c161e6
In linting commands, only lint diff from develop As Weston suggested, there's not much need to lint files that have no diff. This should run in Travis builds, as it does npm run lint.
commit sha 404b770fd20ba2b2a6fbdbc167997c6bc21083c9
If there is no diff to develop, don't lint As described in the issue, there's no need to lint a file with no diff to develop.
commit sha 89ee859a237904ba197004eb26a80827c7bcafca
Add a helper script to be more DRY There probably isn't a need to copy the same command to 3 other places. So add a helper script.
commit sha 546126733ef4d5703b04fa2857d819c2eac4a591
Change diff:develop to diff-develop It looks like most package.json scripts with a colon are for when there are multiple scripts that have the same prefix.
commit sha 740f3d130777dc07cda92ec464a762c81eb78890
Remove pre-commit hook
commit sha 7d35852b1a1efa74b1dc71acd1162bc11e0d7edd
Merge branch 'develop' into update/lint-changed-develop
commit sha 4973402bf40a46e15230822f53781acb20a33dc8
Commit Weston's suggestion for the regex of lint:css Co-Authored-By: Weston Ruter <[email protected]>
commit sha 83e21556ba66a5a33464a9486e883c6ca990c785
Replace diff-develop script with simple git command Instead of registering a new script, simply use that git command.
commit sha 4c40a7537e392258faca25ce80a7b5cc5d4c8b51
Merge branch 'develop' into update/lint-changed-develop
commit sha 6af326bbee51362c8964f96b07011ed38646ee8e
Only run lint command when there are changes
commit sha 485bdfce1a7717ada225f7c90a5e9db382854d08
Remove external script
commit sha c365250ebd5a1df71610b991dc234b235ebef509
Detect file renames
commit sha ab034bce6c1a879c07fedcd4b943ed1413bae14d
Use lint-staged package to perform linting on staged files
commit sha 76a97167473966a7311c92343fde871436c0434e
Only lint, not fix
commit sha 2c8505746cbedc939ad0dc39821565d6ec96bd7f
Directly use phpcs command instead of `lint:plugin-bootstrap` npm script Co-authored-by: Weston Ruter <[email protected]>
commit sha 047e28fb964143b51c468355cdf00f51d7a8b4f6
Merge pull request #4441 from ampproject/update/lint-changed-develop In linting scripts, only lint diff from develop
push time in a day
PR merged ampproject/amp-wp
Summary
- In
package.jsonlinting scripts, this only lints the diff fromdevelop - ~Adds a pre-commit hook, using husky (maybe out of scope for this PR)~
- ~If we don't all want a pre-commit hook, maybe I should revert it. It's not optional in the way the
wp-dev-libpre-commit hook is. It's installed onnpm install.~ - ~The pre-commit hook doesn't overwrite existing pre-commit hooks~
- ~Please do
npm installto install the pre-commit hook~
Fixes #4402
Checklist
- [x] My pull request is addressing an open issue (please create one otherwise).
- [x] My code is tested and passes existing tests. (Manually tested, but unit testing doesn't really apply)
- [x] My code follows the Engineering Guidelines (updates are often made to the guidelines, check it out periodically).
pr closed time in a day
issue closedampproject/amp-wp
Limit linting and fixing to files changed with develop
Feature description
Currently running linting commands like npm run lint:php is slow because it checks every file. We should limit to just checking the files that have changed in comparison with develop. In other words,
vendor/bin/phpcs $(git diff develop --name-only | grep php)
If no PHP files are changed, then it should also just short-circuit.
This should be done for PHP, JS, and CSS.
This will then allow for the lint commands to be added to a pre-commit hook.
The lint:fix commands could also benefit from this.
Do not alter or remove anything below. The following sections will be managed by moderators only.
Acceptance criteria
- <!-- One or more bullet points for acceptance criteria. -->
Implementation brief
- <!-- One or more bullet points for how to technically resolve the issue. For significant Implementation Design, it is ok use a Google document accessible by anyone. -->
QA testing instructions
- <!-- One or more bullet points to describe how to test the implementation in QA. -->
Demo
- <!-- A video or screenshots demoing the implementation. -->
Changelog entry
- <!-- One sentence summarizing the PR, to be used in the changelog. -->
closed time in a day
westonruterPull request review commentampproject/amp-wp
In linting scripts, only lint diff from develop
"test:php": "phpunit", "test:php:help": "npm run test:php -- --help" },+ "lint-staged": {+ "package.json": [+ "npm run lint:pkg-json"+ ],+ "**/*.css": [+ "npm run lint:css"+ ],+ "**/*.js": [+ "npm run lint:js"+ ],+ "**/!(amp).php": [+ "npm run lint:php"+ ],+ "amp.php": [+ "npm run lint:plugin-bootstrap"
This fixes the issue above when linting amp.php:
"vendor/bin/phpcs --runtime-set testVersion 5.2-"
comment created time in 2 days
Pull request review commentampproject/amp-wp
In linting scripts, only lint diff from develop
"lint:js": "wp-scripts lint-js", "lint:js:fix": "npm run lint:js -- --fix", "lint:php": "vendor/bin/phpcs",- "lint:plugin-bootstrap": "vendor/bin/phpcs --runtime-set testVersion 5.2- amp.php", "lint:php:fix": "./bin/phpcbf.sh",+ "lint:plugin-bootstrap": "vendor/bin/phpcs --runtime-set testVersion 5.2- amp.php",
Notice how it is invoking phpcs:
vendor/bin/phpcs --runtime-set testVersion 5.2- amp.php "/app/public/content/plugins/amp/amp.php"
Notice amp.php is being added twice.
comment created time in 2 days
Pull request review commentampproject/amp-wp
In linting scripts, only lint diff from develop
"lint:js": "wp-scripts lint-js", "lint:js:fix": "npm run lint:js -- --fix", "lint:php": "vendor/bin/phpcs",- "lint:plugin-bootstrap": "vendor/bin/phpcs --runtime-set testVersion 5.2- amp.php", "lint:php:fix": "./bin/phpcbf.sh",+ "lint:plugin-bootstrap": "vendor/bin/phpcs --runtime-set testVersion 5.2- amp.php",
For some reason this command is failing for me, when invoked via lint-staged:
$ npm run lint:staged
> amp-wp@ lint:staged /app/public/content/plugins/amp
> lint-staged
✔ Preparing...
✔ Hiding unstaged changes to partially staged files...
⚠ Running tasks...
↓ No staged files match package.json [SKIPPED]
↓ No staged files match **/*.css [SKIPPED]
↓ No staged files match **/*.js [SKIPPED]
✔ Running tasks for **/!(amp).php
❯ Running tasks for amp.php
✖ npm run lint:plugin-bootstrap [FAILED]
↓ Skipped because of errors from tasks. [SKIPPED]
↓ Skipped because of errors from tasks. [SKIPPED]
✔ Reverting to original state because of errors...
✔ Cleaning up...
✖ npm run lint:plugin-bootstrap:
PHP Fatal error: Uncaught PHP_CodeSniffer\Exceptions\RuntimeException: Undefined index: in /app/public/content/plugins/amp/vendor/squizlabs/php_codesniffer/src/Files/FileList.php on line 187 in /app/public/content/plugins/amp/vendor/squizlabs/php_codesniffer/src/Runner.php:606
Stack trace:
#0 /app/public/content/plugins/amp/vendor/squizlabs/php_codesniffer/src/Files/FileList.php(187): PHP_CodeSniffer\Runner->handleErrors(8, 'Undefined index...', '/app/public/con...', 187, Array)
#1 /app/public/content/plugins/amp/vendor/squizlabs/php_codesniffer/src/Runner.php(487): PHP_CodeSniffer\Files\FileList->current()
#2 /app/public/content/plugins/amp/vendor/squizlabs/php_codesniffer/src/Runner.php(114): PHP_CodeSniffer\Runner->run()
#3 /app/public/content/plugins/amp/vendor/squizlabs/php_codesniffer/bin/phpcs(18): PHP_CodeSniffer\Runner->runPHPCS()
#4 {main}
thrown in /app/public/content/plugins/amp/vendor/squizlabs/php_codesniffer/src/Runner.php on line 606
PHP Fatal error: Uncaught PHP_CodeSniffer\Exceptions\RuntimeException: One or more child processes failed to run in /app/public/content/plugins/amp/vendor/squizlabs/php_codesniffer/src/Runner.php:544
Stack trace:
#0 /app/public/content/plugins/amp/vendor/squizlabs/php_codesniffer/src/Runner.php(114): PHP_CodeSniffer\Runner->run()
#1 /app/public/content/plugins/amp/vendor/squizlabs/php_codesniffer/bin/phpcs(18): PHP_CodeSniffer\Runner->runPHPCS()
#2 {main}
thrown in /app/public/content/plugins/amp/vendor/squizlabs/php_codesniffer/src/Runner.php on line 544
npm ERR! code ELIFECYCLE
npm ERR! errno 255
npm ERR! amp-wp@ lint:plugin-bootstrap: `vendor/bin/phpcs --runtime-set testVersion 5.2- amp.php "/app/public/content/plugins/amp/amp.php"`
npm ERR! Exit status 255
npm ERR!
npm ERR! Failed at the amp-wp@ lint:plugin-bootstrap script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! /var/www/.npm/_logs/2020-09-23T03_46_30_988Z-debug.log
> amp-wp@ lint:plugin-bootstrap /app/public/content/plugins/amp
> vendor/bin/phpcs --runtime-set testVersion 5.2- amp.php "/app/public/content/plugins/amp/amp.php"
Fatal error: Uncaught PHP_CodeSniffer\Exceptions\RuntimeException: Undefined index: in /app/public/content/plugins/amp/vendor/squizlabs/php_codesniffer/src/Files/FileList.php on line 187 in /app/public/content/plugins/amp/vendor/squizlabs/php_codesniffer/src/Runner.php:606
Stack trace:
#0 /app/public/content/plugins/amp/vendor/squizlabs/php_codesniffer/src/Files/FileList.php(187): PHP_CodeSniffer\Runner->handleErrors(8, 'Undefined index...', '/app/public/con...', 187, Array)
#1 /app/public/content/plugins/amp/vendor/squizlabs/php_codesniffer/src/Runner.php(487): PHP_CodeSniffer\Files\FileList->current()
#2 /app/public/content/plugins/amp/vendor/squizlabs/php_codesniffer/src/Runner.php(114): PHP_CodeSniffer\Runner->run()
#3 /app/public/content/plugins/amp/vendor/squizlabs/php_codesniffer/bin/phpcs(18): PHP_CodeSniffer\Runner->runPHPCS()
#4 {main}
thrown in /app/public/content/plugins/amp/vendor/squizlabs/php_codesniffer/src/Runner.php on line 606
Fatal error: Uncaught PHP_CodeSniffer\Exceptions\RuntimeException: One or more child processes failed to run in /app/public/content/plugins/amp/vendor/squizlabs/php_codesniffer/src/Runner.php:544
Stack trace:
#0 /app/public/content/plugins/amp/vendor/squizlabs/php_codesniffer/src/Runner.php(114): PHP_CodeSniffer\Runner->run()
#1 /app/public/content/plugins/amp/vendor/squizlabs/php_codesniffer/bin/phpcs(18): PHP_CodeSniffer\Runner->runPHPCS()
#2 {main}
thrown in /app/public/content/plugins/amp/vendor/squizlabs/php_codesniffer/src/Runner.php on line 544
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! amp-wp@ lint:staged: `lint-staged`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the amp-wp@ lint:staged script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! /var/www/.npm/_logs/2020-09-23T03_46_34_383Z-debug.log
comment created time in 2 days
push eventampproject/amp-wp
commit sha 9771152d7f69242331dec9cc194ee0e146fafd68
Bump stable tag 2.0.4 and regenerate docs
push time in 2 days
push eventampproject/amp-wp
commit sha 83f588f53ed1671849a00bc9f5a9fa8cc4a8b518
Bump 2.0.5-alpha
push time in 2 days
created tagampproject/amp-wp
Enable AMP on your WordPress site, the WordPress way.
created time in 2 days
created tagampproject/amp-wp
Enable AMP on your WordPress site, the WordPress way.
created time in 2 days
push eventampproject/amp-wp
commit sha 823ae999158fcd1ae0b2c5c93736103a23fecae9
Bump 2.0.4 and update docs
push time in 2 days
pull request commentampproject/amp-wp
Prevent enabling all post types for AMP when migrating to 2.0 when Reader mode active
Confirmed that when the amp-options option is reset via:
echo '{"theme_support":"reader","supported_post_types":["post"],"analytics":[],"all_templates_supported":true,"supported_templates":["is_singular"],"version":"1.5.5"}' | wp --skip-plugins option set amp-options --format=json
The Supported Templates does not include content types other than post as enabled (since all_templates_supported is not respected):

If I change the theme_support to transitional as follows:
echo '{"theme_support":"transitional","supported_post_types":["post"],"analytics":[],"all_templates_supported":true,"supported_templates":["is_singular"],"version":"1.5.5"}' | wp --skip-plugins option set amp-options --format=json
Then all post types are enabled by default as expected (since all_templates_supported is respected):

comment created time in 2 days
issue closedWordPress/gutenberg
Media upload component does not select or highlight a file in the media library.
Describe the bug I am using a duplicate of the Post Featured Image component for a Newsletter attachment which saves to its own post meta.
However I noticed that the value prop of MediaUpload does not select the file in the media library.
The only way I could get this to happen is to use the unstableFeaturedImageFlow prop, but this is not ideal as it changes the modal to have the wording for a Featured Image - so I had to remove it and live with the file not being pre-selected.
I think this could be fixed by extending the MediaUpload component myself, but its a bit beyond my knowledge at this point. I also don't understand why it should be necessary when the README for the Media Upload component says:
value Media ID (or media IDs if multiple is true) to be selected by default when opening the media library.
To reproduce Make a duplicate of the Post Featured Image component in your own custom sidebar panel. Remove unstableFeaturedImageFlow prop and rely on just the value prop to select the file in the media library.
Expected behavior Value prop of MediaUpload should select the file in the media library using the ID.
Editor version (please complete the following information):
- WordPress version: 5.5.1
- Does the website has Gutenberg plugin installed, or is it using the block editor that comes by default? default
closed time in 2 days
ThatStevensGuyissue commentWordPress/gutenberg
Media upload component does not select or highlight a file in the media library.
AMP plugin issue: https://github.com/ampproject/amp-wp/issues/5379. Fixed via https://github.com/ampproject/amp-wp/pull/5412. This will be part of AMP plugin v2.0.4, which we are releasing today.
comment created time in 2 days
issue commentampproject/amp-wp
WordPress MediaUpload component does not select files when AMP plugin is active.
QA Passed.
I added an audio block, an image block, and set the featured image.
When clicking “replace” for the audio block, the previously-selected audio file was automatically selected:

The same was true for the featured image and image blocks.
comment created time in 2 days
push eventampproject/amp-wp
commit sha 0e03b6469cc9eff98f549e834d535d77383a8296
Bump 2.0.4-RC1
push time in 2 days
push eventampproject/amp-wp
commit sha 307028c4e69ea86505874428cb30c435a608f7cf
Guard against infinite recursion error when validating AMP pages using a Reader theme (#5410) Co-authored-by: Alain Schlesser <[email protected]>
push time in 2 days
push eventampproject/amp-wp
commit sha 54acb48f5b829153cfbba89c8381e590eb027145
Prevent FileReflection from triggering hooks when Reader theme loaded
commit sha bf3d65190ddee8d2df2f67c7ce6d5707c79143fb
Add DI-specific test case
commit sha 5e4d7b38499bdd165e9e7ff35046485ecbd1bd4c
Use injector for ErrorPage as well and make the IDE recognize the return type
commit sha de212723696eeed56712db6a6e82266be6fc0d85
Add missing doc comment
commit sha b724da524b85830bf9b7357c70598d899ecbe42d
Fix test_analyze_backtrace by ensuring custom theme's functions.php is required
commit sha 1afdf5a2957f0165110e22b844ec7fbf7f1b414d
Fix test_filter_wp_prepare_themes_to_indicate_reader_theme
commit sha 3520815b220cecdd7348ce0b3a7ebe77a87fa8f2
Mark DependencyInjectedTestCase as abstract to skip from being tested
commit sha 3cd294ea8d80d19a980c1869d80fb96c67d4b0cf
Deep-link to Reader Themes section from theme card
commit sha 80b4cfb51e4b884ad8b3fb6638f6f1c2a4d520c3
Avoid service container in tests and use injector instead
commit sha b676efbb8c073db6b506c6fa3ef09258137e67e5
Add clarifying comment to DependencyInjectionTestCase about plugin factory
commit sha 51c60a0b6ed7b7a218a270f0bd60b67205022fce
Fix unset index error in reader theme test
commit sha 1179cca2fe23f9661494259af892890bac33a999
Add recursion protection to file reflector
commit sha efd9afcc3db5d325edb6e617cd3fda721087f4e9
Revert previous fix effort
commit sha 90a102be25e3403cc48dbe5e9f425c5fa4026bfd
Fix PHPStan issues
commit sha 639cb4402bd4127910c2720dfe38eaf1ee0ae87a
Remove obsolete ReaderThemeLoader dependency
commit sha ae8afad7eb1e1839e0379cd8ddb98c8f2554d373
Remove amp_options_updating filters to work around unexpected test failure
commit sha 589e8bc9a3311ce2014f419aac426e9925c62eec
Add tearDown() to DependencyInjectedTestCase
commit sha 6513409a058e34e29f0b144132d66fe117b6ba51
Fix PHPCS issue
commit sha ae8766be80dc5818799e90227cad440593a08fa8
Remove unneeded comment
commit sha 5ef559ef2e6466e94087f4554c731a8bb08bdc8e
Merge pull request #5410 from ampproject/fix/reader-theme-validation Guard against infinite recursion error when validating AMP pages using a Reader theme
push time in 2 days
PR merged ampproject/amp-wp
Summary
Fixes #5409
~This PR prevents FileReflection from causing infinite recursion when a Reader theme has been loaded. When the theme has been overridden with a Reader theme, the current theme is obtained via ReaderThemeLoader as opposed to using global functions that have filters.~
This PR adds recursion prevention to \AmpProject\AmpWP\DevTools\FileReflection::get_file_source(). When a Reader theme is loaded (via ReaderThemeLoader), hooks are added to override which theme is active. When validating an AMP page with such a Reader theme, applying those filters can cause infinite recursion since the get_file_source also needs to apply the same filters to determine where a callback is coming from.
Checklist
- [x] My pull request is addressing an open issue (please create one otherwise).
- [x] My code is tested and passes existing tests.
- [x] My code follows the Engineering Guidelines (updates are often made to the guidelines, check it out periodically).
pr closed time in 2 days
issue closedampproject/amp-wp
Validation requests fail due to infinite recursion when Reader theme is selected
Bug Description
I noticed that when a Reader theme is selected, attempting to validate a URL will fail:

The PHP error log includes:
PHP Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 978944 bytes) in /app/public/content/plugins/amp/includes/validation/class-amp-validation-manager.php on line 1328
The issue is that there is either infinite recursion or infinite loop happening here:
https://github.com/ampproject/amp-wp/blob/27718b00bfbaacd4013f1cdbb590dc3f4371b4bf/includes/validation/class-amp-validation-manager.php#L1313-L1323
When the hook is one of:
templatestylesheetpre_option_templatepre_option_stylesheetpre_option_template_rootpre_option_stylesheet_root
This function loop will continue on infinitely and PHP will run out of memory.
These hooks are added by the ReaderThemeLoader:
https://github.com/ampproject/amp-wp/blob/27718b00bfbaacd4013f1cdbb590dc3f4371b4bf/src/ReaderThemeLoader.php#L321-L346
I believe this is a regression introduced by #5289. Specifically, the issue is with FileReflection in these methods:
https://github.com/ampproject/amp-wp/blob/27718b00bfbaacd4013f1cdbb590dc3f4371b4bf/src/DevTools/FileReflection.php#L216-L270
We need to avoid calling get_template_directory() and other such functions
Expected Behaviour
Validation should succeed.
Steps to reproduce
- Activate Reader mode.
- Select a Reader theme.
- Validate a page.
- See error.
Do not alter or remove anything below. The following sections will be managed by moderators only.
Acceptance criteria
- <!-- One or more bullet points for acceptance criteria. -->
Implementation brief
- <!-- One or more bullet points for how to technically resolve the issue. For significant Implementation Design, it is ok use a Google document accessible by anyone. -->
QA testing instructions
- <!-- One or more bullet points to describe how to test the implementation in QA. -->
Demo
- <!-- A video or screenshots demoing the implementation. -->
Changelog entry
- <!-- One sentence summarizing the PR, to be used in the changelog. -->
closed time in 2 days
westonruterissue commentampproject/amp-wp
Increase clarity and improve placement of featured image size recommendation
- The reason for the recommendation should be made clear. If I understand correctly, it derives from the recommendations here: https://developers.google.com/search/docs/data-types/article#article_types But valid structured data might not be important to all users.
That is correct. The reason it doesn't mention AMP specifically, is that it is a general Google Search recommendation/requirement. Nevertheless, you're right that some users won't care. It's just that when Google Search Console complains about missing structured data or an image that is too small, we want to be able to say that we warned them.
comment created time in 2 days
issue commentampproject/amp-wp
Improve discoverability of “Save Changes” button on AMP settings screen
@jwold I don't think the button should become the notice, as otherwise what will the user click to retry? Clicking “Save Error” seems to indicate that the error would be saved. I think the success and error notices should be floated to the right.
comment created time in 2 days
Pull request review commentampproject/amp-wp
Guard against infinite recursion error when validating AMP pages using a Reader theme
+<?php++namespace AmpProject\AmpWP\Tests;++use AmpProject\AmpWP\AmpWpPlugin;+use AmpProject\AmpWP\Infrastructure\Injector;+use AmpProject\AmpWP\Infrastructure\ServiceContainer;+use AmpProject\AmpWP\Services;+use AmpProject\AmpWP\Tests\Helpers\PrivateAccess;+use WP_UnitTestCase;++abstract class DependencyInjectedTestCase extends WP_UnitTestCase {++ use PrivateAccess;++ /**+ * Plugin instance to test with.+ *+ * @var AmpWpPlugin+ */+ protected $plugin;++ /**+ * Service container instance to test with.+ *+ * @var ServiceContainer+ */+ protected $container;++ /**+ * Injector instance to test with.+ *+ * @var Injector+ */+ protected $injector;++ /**+ * Runs the routine before each test is executed.+ */+ public function setUp() {+ parent::setUp();++ // We're intentionally avoiding the AmpWpPluginFactory here as it uses a+ // static instance, because its whole point is to allow reuse across consumers.+ $this->plugin = new AmpWpPlugin();+ $this->plugin->register();++ $this->container = $this->plugin->get_container();+ $this->injector = $this->container->get( 'injector' );++ // The static Services helper has to be modified to use the same objects+ // as the ones that are injected into the tests.+ $this->set_private_property( Services::class, 'plugin', $this->plugin );+ $this->set_private_property( Services::class, 'container', $this->container );+ $this->set_private_property( Services::class, 'injector', $this->injector );
Looks good: 589e8bc9a3311ce2014f419aac426e9925c62eec
comment created time in 2 days





(Removed by plugin sanitizer)
(No change)
(No change)
(No-JS fallback!)
