-
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
Fix validation error due to native img tag when lightbox and carousel is enabled #7158
Conversation
…attr for native img
Plugin builds for 3e558de are ready 🛎️!
|
3837bfb
to
762c309
Compare
$img_elements = $this->dom->xpath->query( | ||
'.//img[ @layout = "fill" or @object-fit = "cover" ]', | ||
$this->dom->body | ||
); | ||
|
||
/* | ||
* Remove `layout` and `object-fit` attributes from native img as they are not supported by AMP yet. | ||
* Add style attribute which is used to set `object-fit` and `layout` attributes. | ||
* @see <https://github.com/ampproject/amp-wp/issues/7152#issuecomment-1157933188> | ||
* @todo Remove this once `layout` and `object-fit` attributes are supported by AMP spec for native img tag. | ||
*/ | ||
$style_layout_fill = 'position:absolute; left:0; right:0; top:0; bottom: 0; width:100%; height:100%;'; | ||
$style_object_fit = 'object-fit:cover;'; | ||
foreach ( $img_elements as $img_element ) { | ||
$remove_layout_attr = $img_element->removeAttribute( Attribute::LAYOUT ); | ||
$remove_object_fit_attr = $img_element->removeAttribute( Attribute::OBJECT_FIT ); | ||
$style_attr_content = sprintf( '%s %s', $remove_layout_attr ? $style_layout_fill : '', $remove_object_fit_attr ? $style_object_fit : '' ); | ||
|
||
if ( ' ' !== $style_attr_content ) { | ||
$img_element->setAttribute( Attribute::STYLE, $style_attr_content ); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this logic may make more sense in the image sanitizer, specifically in the adjust_and_replace_node
method:
amp-wp/includes/sanitizers/class-amp-img-sanitizer.php
Lines 402 to 422 in bbf48d7
private function adjust_and_replace_node( Element $node ) { | |
if ( $this->args['native_img_used'] || ( $node->parentNode instanceof Element && Tag::PICTURE === $node->parentNode->tagName ) ) { | |
$attributes = $this->maybe_add_lightbox_attributes( [], $node ); // @todo AMP doesn't support lightbox on <img> yet. | |
// Set decoding=async by default. See <https://core.trac.wordpress.org/ticket/53232>. | |
if ( ! $node->hasAttribute( Attribute::DECODING ) ) { | |
$attributes[ Attribute::DECODING ] = 'async'; | |
} | |
// @todo This class should really only be added if we actually have to provide dimensions. | |
$attributes[ Attribute::CLASS_ ] = (string) $node->getAttribute( Attribute::CLASS_ ); | |
if ( ! empty( $attributes[ Attribute::CLASS_ ] ) ) { | |
$attributes[ Attribute::CLASS_ ] .= ' '; | |
} | |
$attributes[ Attribute::CLASS_ ] .= 'amp-wp-enforced-sizes'; | |
foreach ( $attributes as $name => $value ) { | |
$node->setAttribute( $name, $value ); | |
} | |
return; | |
} |
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.
Where you're currently adding the lightbox
handling.
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.
Where you're currently adding the lightbox handling.
Handling it in the image sanitizer because need to check if an image has lightbox
enabled to not.
amp-wp/includes/sanitizers/class-amp-img-sanitizer.php
Lines 405 to 418 in 60e2f46
/* | |
* Mark lightbox as px-verified attribute until it's supported by AMP spec. | |
* @see <https://github.com/ampproject/amp-wp/issues/7152#issuecomment-1157933188> | |
* @todo Remove this once lightbox is added in `lightboxable-elements` for native img tag in AMP spec. | |
*/ | |
if ( isset( $attributes['data-amp-lightbox'] ) ) { | |
$node->setAttribute( Attribute::LIGHTBOX, 'true' ); | |
$node_attr = $node->getAttributeNode( Attribute::LIGHTBOX ); | |
if ( $node_attr instanceof DOMAttr ) { | |
ValidationExemption::mark_node_as_px_verified( $node_attr ); | |
} | |
} | |
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 mean, I think the logic here would all make more sense in the image sanitizer.
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.
Oh, but the problem is that AMP_Gallery_Block_Sanitizer
runs after AMP_Img_Sanitizer
.
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.
Are you still planning to try to move this code to the img sanitizer by changing the order that the sanitizers run in? That is, if the gallery block sanitizer runs before the image sanitizer then the logic should be able to be consolidated in the img sanitizer.
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.
Are you still planning to try to move this code
I have tried it locally but changing the order of sanitizers causes markup error as the gallery block expects sanitized images.
One more idea that came up to my mind is to create a mini native IMG attributes sanitizer which can be called after gallery block. Doing so can help to sanitize more attributes if required in near future.
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 do like your idea of having a new mini native img sanitizer that runs after the gallery sanitizer to specifically handle the lightbox
, layout
, and object-fit
attributes. It would be better yet to have it run in the img sanitizer, but consolidating them into one special sanitizer is better than having them spread out across two sanitizers as they are now.
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.
So, should I create a mini native img attributes sanitizer?
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.
Yes, please create an AMP_Native_Img_Attributes_Sanitizer
.
Co-authored-by: Weston Ruter <westonruter@google.com>
1accc15
to
e4e5396
Compare
6a8c84e
to
d4705ee
Compare
…box-with-native-img * 'develop' of github.com:ampproject/amp-wp: Bump moment from 2.29.3 to 2.29.4 Bump eslint from 8.18.0 to 8.19.0 Bump dependabot/fetch-metadata from 1.3.2 to 1.3.3 Bump dependabot/fetch-metadata from 1.3.1 to 1.3.2 Bump @babel/plugin-proposal-class-properties from 7.17.12 to 7.18.6 Bump @babel/core from 7.18.5 to 7.18.6 Bump eslint-plugin-react from 7.30.0 to 7.30.1 Bump lint-staged from 13.0.2 to 13.0.3 Bump postcss-preset-env from 7.7.1 to 7.7.2 Bump shell-quote from 1.7.2 to 1.7.3 Bump guzzlehttp/guzzle from 6.5.7 to 6.5.8 Bump eslint-plugin-jsdoc from 39.3.2 to 39.3.3 Bump eslint from 8.17.0 to 8.18.0
includes/sanitizers/class-amp-native-img-attributes-sanitizer.php
Outdated
Show resolved
Hide resolved
includes/sanitizers/class-amp-native-img-attributes-sanitizer.php
Outdated
Show resolved
Hide resolved
// Images with object-fit attributes. | ||
$img_elements = $this->dom->xpath->query( | ||
'.//img[ @object-fit ]', | ||
$this->dom->body | ||
); | ||
if ( $img_elements instanceof DOMNodeList ) { | ||
foreach ( $img_elements as $img_element ) { | ||
/** @var Element $img_element */ | ||
$value = $img_element->getAttribute( Attribute::OBJECT_FIT ); | ||
$img_element->removeAttribute( Attribute::OBJECT_FIT ); | ||
$img_element->addInlineStyle( sprintf( 'object-fit:%s', $value ) ); | ||
} | ||
} | ||
|
||
// Images with object-position attributes. | ||
$img_elements = $this->dom->xpath->query( | ||
'.//img[ @object-position ]', | ||
$this->dom->body | ||
); | ||
if ( $img_elements instanceof DOMNodeList ) { | ||
foreach ( $img_elements as $img_element ) { | ||
/** @var Element $img_element */ | ||
$value = $img_element->getAttribute( Attribute::OBJECT_POSITION ); | ||
$img_element->removeAttribute( Attribute::OBJECT_POSITION ); | ||
$img_element->addInlineStyle( sprintf( 'object-position:%s', $value ) ); | ||
} | ||
} |
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.
It turns out that amp-video
also supports object-fit
and object-position
attributes, so it could be that there could end up being some video
elements that have these attributes. In this case, the sanitizer could be made more generic instead of being specifically for images. But since we don't have any known cases of this happening for video, this could be done later. Or it could be done now if you want.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't think of any such use case. IMO we are amending changes to img
tags only so can't we keep it as it is?
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 mean, it could be that a theme/plugin author is adding: <video object-fit=cover …>
and is then relying on the fact that this is converged to <amp-video object-fit=cover>
. But in moderate sandboxing, no conversion is being done, so this would then be a validation error and the attribute should be moved to style
as we're doing for img
.
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.
Oh. got it now. But I think a new PR should introduce it instead of adding it in the same. Also as mentioned But since we don't have any known cases of this happening for video, this could be done later.
IMO adding it with some use case make more sense. Thoughts?
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.
If a user reports this issue we can follow up with the change.
Summary
This PR aims to fix validation errors by using the native
img
tag.Errors:
<img>
tag by amp validator yet.layout
andobject-fir
attributes are not identified in<img>
tag by amp validator yet.When adding lightbox and carousel with native img used:
Before:
After:
Fixes #7152
Checklist