Skip to content

Commit ee80e10

Browse files
committed
Preserve original styles; support object-position; support non-cover object-fit
1 parent 144b65f commit ee80e10

File tree

2 files changed

+92
-26
lines changed

2 files changed

+92
-26
lines changed

includes/sanitizers/class-amp-native-img-attributes-sanitizer.php

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
use AmpProject\Html\Attribute;
1010
use AmpProject\Dom\Element;
11+
use AmpProject\Layout;
1112

1213
/**
1314
* Class AMP_Native_Img_Attributes_Sanitizer
@@ -46,27 +47,44 @@ public function sanitize() {
4647
return;
4748
}
4849

50+
// Images with layout=fill.
4951
$img_elements = $this->dom->xpath->query(
50-
'.//img[ @layout = "fill" or @object-fit = "cover" ]',
52+
'.//img[ @layout = "fill" ]',
5153
$this->dom->body
5254
);
53-
54-
if ( ! $img_elements instanceof DOMNodeList || 0 === $img_elements->length ) {
55-
return;
55+
if ( $img_elements instanceof DOMNodeList ) {
56+
foreach ( $img_elements as $img_element ) {
57+
/** @var Element $img_element */
58+
$img_element->removeAttribute( Attribute::LAYOUT );
59+
$img_element->addInlineStyle( 'position:absolute;left:0;right:0;top:0;bottom:0;width:100%;height:100%' );
60+
}
5661
}
5762

58-
$style_layout_fill = 'position:absolute; left:0; right:0; top:0; bottom: 0; width:100%; height:100%;';
59-
$style_object_fit = 'object-fit:cover;';
60-
61-
foreach ( $img_elements as $img_element ) {
62-
/** @var Element $img_element */
63-
64-
$remove_layout_attr = $img_element->removeAttribute( Attribute::LAYOUT );
65-
$remove_object_fit_attr = $img_element->removeAttribute( Attribute::OBJECT_FIT );
66-
$style_attr_content = sprintf( '%s %s', $remove_layout_attr ? $style_layout_fill : '', $remove_object_fit_attr ? $style_object_fit : '' );
63+
// Images with object-fit attributes.
64+
$img_elements = $this->dom->xpath->query(
65+
'.//img[ @object-fit ]',
66+
$this->dom->body
67+
);
68+
if ( $img_elements instanceof DOMNodeList ) {
69+
foreach ( $img_elements as $img_element ) {
70+
/** @var Element $img_element */
71+
$value = $img_element->getAttribute( Attribute::OBJECT_FIT );
72+
$img_element->removeAttribute( Attribute::OBJECT_FIT );
73+
$img_element->addInlineStyle( sprintf( 'object-fit:%s', $value ) );
74+
}
75+
}
6776

68-
if ( ' ' !== $style_attr_content ) {
69-
$img_element->setAttribute( Attribute::STYLE, $style_attr_content );
77+
// Images with object-position attributes.
78+
$img_elements = $this->dom->xpath->query(
79+
'.//img[ @object-position ]',
80+
$this->dom->body
81+
);
82+
if ( $img_elements instanceof DOMNodeList ) {
83+
foreach ( $img_elements as $img_element ) {
84+
/** @var Element $img_element */
85+
$value = $img_element->getAttribute( Attribute::OBJECT_POSITION );
86+
$img_element->removeAttribute( Attribute::OBJECT_POSITION );
87+
$img_element->addInlineStyle( sprintf( 'object-position:%s', $value ) );
7088
}
7189
}
7290
}

tests/php/test-class-amp-native-img-attributes-sanitizer.php

Lines changed: 59 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*/
77

88
use AmpProject\AmpWP\Tests\TestCase;
9+
use AmpProject\AmpWP\Tests\Helpers\MarkupComparison;
910

1011
/**
1112
* Class AMP_Native_Img_Attributes_Sanitizer_Test
@@ -15,30 +16,77 @@
1516
*/
1617
class AMP_Native_Img_Attributes_Sanitizer_Test extends TestCase {
1718

19+
use MarkupComparison;
20+
21+
public function get_data_to_test_sanitize() {
22+
$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>';
23+
$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>';
24+
25+
return [
26+
'disabled' => [
27+
false,
28+
$amp_carousel_source,
29+
null, // Same as above.
30+
],
31+
'carousel_with_img' => [
32+
true,
33+
$amp_carousel_source,
34+
$amp_carousel_sanitized,
35+
],
36+
'amp_img' => [
37+
true,
38+
'<amp-img src="https://example.com/img.png" style="border: solid 1px red;" layout="fill" object-fit="cover"></amp-img>',
39+
null, // Same as above.
40+
],
41+
'img_with_layout_fill' => [
42+
true,
43+
'<img src="https://example.com/img.png" style="border: solid 1px red" layout="fill">',
44+
'<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%">',
45+
],
46+
'img_with_layout_nodisplay' => [
47+
true,
48+
'<img src="https://example.com/img.png" style="border: solid 1px red;" layout="nodisplay">',
49+
null, // Same as above.
50+
],
51+
'img_with_object_fit_cover' => [
52+
true,
53+
'<img src="https://example.com/img.png" style="border: solid 1px red;" object-fit="cover">',
54+
'<img src="https://example.com/img.png" style="border: solid 1px red;object-fit:cover">',
55+
],
56+
'img_with_object_fit_contain' => [
57+
true,
58+
'<img src="https://example.com/img.png" style="border: solid 1px red;" object-fit="contain">',
59+
'<img src="https://example.com/img.png" style="border: solid 1px red;object-fit:contain">',
60+
],
61+
'img_with_object_position' => [
62+
true,
63+
'<img src="https://example.com/img.png" style="border: solid 1px red;" object-position="top">',
64+
'<img src="https://example.com/img.png" style="border: solid 1px red;object-position:top">',
65+
],
66+
];
67+
}
68+
1869
/**
1970
* Test an native img tag has not layout or object-fit attributes.
2071
*
2172
* `layout` and `object-fit` will be replaced with a style attribute.
2273
*
23-
* @covers \AMP_Native_Img_Attributes_Sanitizer::sanitize()
74+
* @dataProvider get_data_to_test_sanitize
75+
* @covers ::sanitize()
2476
*/
25-
public function test_native_img_tag_has_not_layout_or_object_fit_attrs() {
26-
$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>';
27-
$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>';
77+
public function test_sanitize( $native_img_used, $source, $expected ) {
78+
if ( null === $expected ) {
79+
$expected = $source;
80+
}
2881

2982
$dom = AMP_DOM_Utils::get_dom_from_content( $source );
3083
$sanitizer = new AMP_Native_Img_Attributes_Sanitizer(
3184
$dom,
32-
[
33-
'native_img_used' => true,
34-
'carousel_required' => true,
35-
]
85+
compact( 'native_img_used' )
3686
);
3787
$sanitizer->sanitize();
3888

39-
$sanitizer = new AMP_Tag_And_Attribute_Sanitizer( $dom );
40-
$sanitizer->sanitize();
4189
$content = AMP_DOM_Utils::get_content_from_dom( $dom );
42-
$this->assertEquals( $expected, $content );
90+
$this->assertEqualMarkup( $expected, $content );
4391
}
4492
}

0 commit comments

Comments
 (0)