Skip to content

Commit

Permalink
Preserve original styles; support object-position; support non-cover …
Browse files Browse the repository at this point in the history
…object-fit
  • Loading branch information
westonruter committed Jul 7, 2022
1 parent 144b65f commit ee80e10
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 26 deletions.
48 changes: 33 additions & 15 deletions includes/sanitizers/class-amp-native-img-attributes-sanitizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

use AmpProject\Html\Attribute;
use AmpProject\Dom\Element;
use AmpProject\Layout;

/**
* Class AMP_Native_Img_Attributes_Sanitizer
Expand Down Expand Up @@ -46,27 +47,44 @@ public function sanitize() {
return;
}

// Images with layout=fill.
$img_elements = $this->dom->xpath->query(
'.//img[ @layout = "fill" or @object-fit = "cover" ]',
'.//img[ @layout = "fill" ]',
$this->dom->body
);

if ( ! $img_elements instanceof DOMNodeList || 0 === $img_elements->length ) {
return;
if ( $img_elements instanceof DOMNodeList ) {
foreach ( $img_elements as $img_element ) {
/** @var Element $img_element */
$img_element->removeAttribute( Attribute::LAYOUT );
$img_element->addInlineStyle( 'position:absolute;left:0;right:0;top:0;bottom:0;width:100%;height:100%' );
}
}

$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 ) {
/** @var Element $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 : '' );
// 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 ) );
}
}

if ( ' ' !== $style_attr_content ) {
$img_element->setAttribute( Attribute::STYLE, $style_attr_content );
// 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 ) );
}
}
}
Expand Down
70 changes: 59 additions & 11 deletions tests/php/test-class-amp-native-img-attributes-sanitizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/

use AmpProject\AmpWP\Tests\TestCase;
use AmpProject\AmpWP\Tests\Helpers\MarkupComparison;

/**
* Class AMP_Native_Img_Attributes_Sanitizer_Test
Expand All @@ -15,30 +16,77 @@
*/
class AMP_Native_Img_Attributes_Sanitizer_Test extends TestCase {

use MarkupComparison;

public function get_data_to_test_sanitize() {
$amp_carousel_source = '<amp-carousel width="600" height="400" type="slides" layout="responsive" lightbox=""><figure class="slide"><img src="http://example.com/img.png" width="600" height="400" layout="fill" object-fit="cover"></figure></amp-carousel>';
$amp_carousel_sanitized = '<amp-carousel width="600" height="400" type="slides" layout="responsive" lightbox=""><figure class="slide"><img src="http://example.com/img.png" width="600" height="400" style="position:absolute;left:0;right:0;top:0;bottom:0;width:100%;height:100%;object-fit:cover"></figure></amp-carousel>';

return [
'disabled' => [
false,
$amp_carousel_source,
null, // Same as above.
],
'carousel_with_img' => [
true,
$amp_carousel_source,
$amp_carousel_sanitized,
],
'amp_img' => [
true,
'<amp-img src="https://example.com/img.png" style="border: solid 1px red;" layout="fill" object-fit="cover"></amp-img>',
null, // Same as above.
],
'img_with_layout_fill' => [
true,
'<img src="https://example.com/img.png" style="border: solid 1px red" layout="fill">',
'<img src="https://example.com/img.png" style="border: solid 1px red;position:absolute;left:0;right:0;top:0;bottom:0;width:100%;height:100%">',
],
'img_with_layout_nodisplay' => [
true,
'<img src="https://example.com/img.png" style="border: solid 1px red;" layout="nodisplay">',
null, // Same as above.
],
'img_with_object_fit_cover' => [
true,
'<img src="https://example.com/img.png" style="border: solid 1px red;" object-fit="cover">',
'<img src="https://example.com/img.png" style="border: solid 1px red;object-fit:cover">',
],
'img_with_object_fit_contain' => [
true,
'<img src="https://example.com/img.png" style="border: solid 1px red;" object-fit="contain">',
'<img src="https://example.com/img.png" style="border: solid 1px red;object-fit:contain">',
],
'img_with_object_position' => [
true,
'<img src="https://example.com/img.png" style="border: solid 1px red;" object-position="top">',
'<img src="https://example.com/img.png" style="border: solid 1px red;object-position:top">',
],
];
}

/**
* Test an native img tag has not layout or object-fit attributes.
*
* `layout` and `object-fit` will be replaced with a style attribute.
*
* @covers \AMP_Native_Img_Attributes_Sanitizer::sanitize()
* @dataProvider get_data_to_test_sanitize
* @covers ::sanitize()
*/
public function test_native_img_tag_has_not_layout_or_object_fit_attrs() {
$source = '<amp-carousel width="600" height="400" type="slides" layout="responsive" lightbox=""><figure class="slide"><img src="http://example.com/img.png" width="600" height="400" layout="fill" object-fit="cover"></figure></amp-carousel>';
$expected = '<amp-carousel width="600" height="400" type="slides" layout="responsive" lightbox=""><figure class="slide"><img src="http://example.com/img.png" width="600" height="400" style="position:absolute; left:0; right:0; top:0; bottom: 0; width:100%; height:100%; object-fit:cover;"></figure></amp-carousel>';
public function test_sanitize( $native_img_used, $source, $expected ) {
if ( null === $expected ) {
$expected = $source;
}

$dom = AMP_DOM_Utils::get_dom_from_content( $source );
$sanitizer = new AMP_Native_Img_Attributes_Sanitizer(
$dom,
[
'native_img_used' => true,
'carousel_required' => true,
]
compact( 'native_img_used' )
);
$sanitizer->sanitize();

$sanitizer = new AMP_Tag_And_Attribute_Sanitizer( $dom );
$sanitizer->sanitize();
$content = AMP_DOM_Utils::get_content_from_dom( $dom );
$this->assertEquals( $expected, $content );
$this->assertEqualMarkup( $expected, $content );
}
}

1 comment on commit ee80e10

@thelovekesh
Copy link
Collaborator

Choose a reason for hiding this comment

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

Thanks for the catch-up 🙌🏼 . I was also working but it looks in better shape now 😄 .

Please sign in to comment.