-
Notifications
You must be signed in to change notification settings - Fork 384
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Remove scripts for components that were not detected in output buffer #3705
Conversation
@westonruter I had to change a few existing tests to get them to pass, as this now removes any AMP component script that is not detected in the output buffer. This might have side effects:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes work as expected, nice work @schlessera 👌
That's a great question. I'll inquire.
Yes, the featured image for example gets sanitized separately from the content. However, the scripts gleaned from it will get merged with the scripts gleaned from |
@schlessera Can you elaborate on this? I'm not sure I understand. |
I've inquired in #validator-discuss on AMP Slack:
|
FYI: If you rebase against |
includes/class-amp-theme-support.php
Outdated
$custom_element = $amp_scripts[ $superfluous_script_handle ]->getAttribute( 'custom-element' ); | ||
|
||
// Skip dynamic CSS classes script, it has no associated element. | ||
if ( 'amp-dynamic-css-classes' === $custom_element ) { | ||
continue; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of doing this single check here, and depending on what the AMP validator team comes back with regarding any list of components, perhaps [ 'amp-dynamic-css-classes' ]
should be merged with $script_handles
when it is passed into array_diff()
. Then there would be no need for $custom_element
, as the script handles are the component names.
includes/class-amp-theme-support.php
Outdated
@@ -1745,6 +1745,30 @@ public static function ensure_required_markup( DOMDocument $dom, $script_handles | |||
$amp_scripts[ $missing_script_handle ] = AMP_DOM_Utils::create_node( $dom, 'script', $attrs ); | |||
} | |||
|
|||
// Remove scripts that had already been added but couldn't be detected from output buffering. | |||
foreach ( array_diff( array_keys( $amp_scripts ), $script_handles ) as $superfluous_script_handle ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
array_diff( array_keys( $amp_scripts ), $script_handles )
may need to be array_intersect()
'ed with a list of components that are actually prone to cause validation errors. Scripts like amp-video
and amp-form
don't cause any issue when being included. Perhaps this is due to some having built-in status. We need to find out.
In that case, there would be no need for the amp-dynamic-css-classes
check below either.
Sorry, I updated the comment, it was missing a word:
What I mean by that is that the scripts are only added to our list of detected scripts if we actually do check for the component that is associated for that script. If a component is part of the markup that we don't check for (new component, maybe?), then we will also not detect the need for that script, and will consequently strip it if it was already included. |
Replies courtesy of @honeybadgerdontcare.
The feature to enforce this was released after AMP was released and to enforce it on all previous scripts at that time would have broken many AMP documents. Instead those previous scripts were grandfathered in. More can be read at https://github.com/ampproject/amphtml/blob/master/validator/validator.proto#L430
These would be declared as requires_usage: NONE. The list could be derived from parsing the protoascii and looking at the requires_usage portion of an extension_spec. https://github.com/ampproject/amphtml/blob/master/validator/validator.proto#L454 PR ampproject/amphtml#22528 introduced a JSON version of the validator spec that might be useful here. |
For this see #2769.
This is great. What we can do in the immediate term is update the spec parser Python script to extract the |
…ve-duplicate-amp-scripts * 'develop' of github.com:ampproject/amp-wp: (66 commits) Improve display of validation errors for scripts (#3722) Conditionally run E2E tests (#3723) Tidy up validation error details (#3721) Add missing space after sentence (#3720) Default to the homepage instead of fetching the first AMP compatible post to customize (#3715) Include text content of style element in validation error (#3717) Fix summarizing error sources both parent theme and child theme (#3709) Exclude WordPress.PHP.DisallowShortTernary phpcs sniff Fix phpcs issues with date() and current_time() Exclude Generic.Arrays.DisallowShortArraySyntax from WordPress-Core Update dependency wp-coding-standards/wpcs to v2.2.0 Improve specificity of JS doc Fix identifying sources for validation errors coming child themes (#3708) Fix failing E2E tests (#3707) Remove amp_validate query var from Validated URL 'View' row action Re-factor get_html_attribute_pattern as match_element_attributes Quote variables added to regex pattern Replace incorrect usage of esc_url() with esc_url_raw() Remove empty alt attributes Add object-fit=contain to amp-youtube placeholder image ...
includes/amp-helper-functions.php
Outdated
$src, | ||
[ 'amp-runtime' ], | ||
null | ||
); | ||
|
||
$wp_scripts->add_data( $extension_spec['name'], 'amp_requires_usage', ! empty( $extension_spec['requires_usage'] ) ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not super happy with what I did here. The post-processor shouldn't be looking at the wp_scripts()
object to determine later if this requires usage. It would be better if the extension_specs
were obtained again during post-processing and the required_usage
was obtained at that point.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about even moving the entire registration to a point where we know what is needed and what is not? That would avoid registering scripts we don't need, and you could have all checks against the spec in one place...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These scripts are needing to be registered in WP_Scripts
to ensure that they will be available to enqueue for AMP components used outside of AMP pages. For example, Newspack is using amp-carousel
in its Carousel block and the block will wp_enqueue_script( 'amp-carousel' )
which will ensure it works in AMP pages and non-AMP pages alike. (Granted, this is not guaranteed to work prior to Bento AMP, but still, it works most of the time and is better than a blank element.)
includes/amp-helper-functions.php
Outdated
$versions = $script_spec[ AMP_Rule_Spec::TAG_SPEC ]['extension_spec']['version']; | ||
array_pop( $versions ); | ||
$extensions[ $script_spec[ AMP_Rule_Spec::TAG_SPEC ]['extension_spec']['name'] ] = array_pop( $versions ); | ||
if ( ! isset( $script_spec[ AMP_Rule_Spec::TAG_SPEC ]['extension_spec'] ) ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Python parser should probably be smarter about extracting all of the extension specs up front to then provide them in a single call, like AMP_Allowed_Tags_Generated::get_extension_specs()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should at one point rethink the way the spec is parsed. I've created an issue for that: #3730
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I love that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While we plan out improving how the spec is parsed, I've implemented a AMP_Allowed_Tags_Generated::get_extension_specs()
helper to improve things in the meantime. See 9956c90.
…ve-duplicate-amp-scripts * 'develop' of github.com:ampproject/amp-wp: Manually add copies of AMP scripts rather than using wp_print_scripts() Add duplicate scripts to head as well Add test for removing duplicate scripts Bump stable tag to 1.4.1 Update screenshots for 1.4.1 Fix expected image name after upstream change (#3749) Use length property instead of count() method on DOMNodeList (#3727)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, cannot request changes as the author of the PR... (silly limitation).
bin/amphtml-update.py
Outdated
public static function get_extension_specs() { | ||
$extension_specs = []; | ||
foreach ( self::get_allowed_tag( 'script' ) as $script_spec ) { | ||
if ( isset( $script_spec[ AMP_Rule_Spec::TAG_SPEC ]['extension_spec'] ) ) { | ||
$extension_specs[ $script_spec[ AMP_Rule_Spec::TAG_SPEC ]['extension_spec']['name'] ] = $script_spec[ AMP_Rule_Spec::TAG_SPEC ]['extension_spec']; | ||
} | ||
} | ||
return $extension_specs; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to process this every time it is requested (which is at least twice per request).
public static function get_extension_specs() {
static $extension_specs = [];
if ( ! empty( $extension_specs ) ) {
return $extension_specs;
}
foreach ( self::get_allowed_tag( 'script' ) as $script_spec ) {
if ( isset( $script_spec[ AMP_Rule_Spec::TAG_SPEC ]['extension_spec'] ) ) {
$extension_specs[ $script_spec[ AMP_Rule_Spec::TAG_SPEC ]['extension_spec']['name'] ] = $script_spec[ AMP_Rule_Spec::TAG_SPEC ]['extension_spec'];
}
}
return $extension_specs;
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point. Done in 16f35b4.
Summary
If there are AMP scripts present on the page which are not present in
$script_handles
then they are removed, as otherwise there can be an AMP validation error (as they are unused).Fixes #3489
Checklist