diff --git a/includes/class-amp-theme-support.php b/includes/class-amp-theme-support.php
index c9154f33454..16a8d5d0c01 100644
--- a/includes/class-amp-theme-support.php
+++ b/includes/class-amp-theme-support.php
@@ -248,6 +248,7 @@ public static function add_hooks() {
add_filter( 'cancel_comment_reply_link', array( __CLASS__, 'filter_cancel_comment_reply_link' ), 10, 3 );
add_action( 'comment_form', array( __CLASS__, 'amend_comment_form' ), 100 );
remove_action( 'comment_form', 'wp_comment_form_unfiltered_html_nonce' );
+ add_filter( 'wp_kses_allowed_html', array( __CLASS__, 'whitelist_layout_in_wp_kses_allowed_html' ), 10 );
if ( AMP_Validation_Utils::should_validate_response() ) {
AMP_Validation_Utils::add_validation_hooks();
@@ -1113,6 +1114,22 @@ public static function prepare_response( $response, $args = array() ) {
return $response;
}
+ /**
+ * Adds 'data-amp-layout' to the allowed attributes for wp_kses().
+ *
+ * @since 0.7
+ *
+ * @param array $context Allowed tags and their allowed attributes.
+ * @return array $context Filtered allowed tags and attributes.
+ */
+ public static function whitelist_layout_in_wp_kses_allowed_html( $context ) {
+ if ( ! empty( $context['img']['width'] ) && ! empty( $context['img']['height'] ) ) {
+ $context['img']['data-amp-layout'] = true;
+ }
+
+ return $context;
+ }
+
/**
* Enqueue AMP assets if this is an AMP endpoint.
*
diff --git a/includes/sanitizers/class-amp-base-sanitizer.php b/includes/sanitizers/class-amp-base-sanitizer.php
index cecf6325ae7..0fc9a697085 100644
--- a/includes/sanitizers/class-amp-base-sanitizer.php
+++ b/includes/sanitizers/class-amp-base-sanitizer.php
@@ -201,7 +201,7 @@ public function sanitize_dimension( $value, $dimension ) {
}
/**
- * Enforce fixed height.
+ * Sets the layout, and possibly the 'height' and 'width' attributes.
*
* @param string[] $attributes {
* Attributes.
@@ -214,12 +214,11 @@ public function sanitize_dimension( $value, $dimension ) {
* }
* @return string[]
*/
- public function enforce_fixed_height( $attributes ) {
+ public function set_layout( $attributes ) {
if ( empty( $attributes['height'] ) ) {
unset( $attributes['width'] );
$attributes['height'] = self::FALLBACK_HEIGHT;
}
-
if ( empty( $attributes['width'] ) ) {
$attributes['layout'] = 'fixed-height';
}
@@ -227,47 +226,6 @@ public function enforce_fixed_height( $attributes ) {
return $attributes;
}
- /**
- * This is our workaround to enforce max sizing with layout=responsive.
- *
- * We want elements to not grow beyond their width and shrink to fill the screen on viewports smaller than their width.
- *
- * See https://github.com/ampproject/amphtml/issues/1280#issuecomment-171533526
- * See https://github.com/Automattic/amp-wp/issues/101
- *
- * @param string[] $attributes {
- * Attributes.
- *
- * @type int $height
- * @type int $width
- * @type string $sizes
- * @type string $class
- * @type string $layout
- * }
- * @return string[]
- */
- public function enforce_sizes_attribute( $attributes ) {
- if ( ! isset( $attributes['width'], $attributes['height'] ) ) {
- return $attributes;
- }
-
- $max_width = $attributes['width'];
- if ( isset( $this->args['content_max_width'] ) && $max_width >= $this->args['content_max_width'] ) {
- $max_width = $this->args['content_max_width'];
- }
-
- // Allows floats and integers but prevents negative values.
- // Uses string format to prevent additional modification.
- $attributes['sizes'] = sprintf(
- '(min-width: %1$spx) %1$spx, 100vw',
- max( 0, floatval( $max_width ) )
- );
-
- $this->add_or_append_attribute( $attributes, 'class', 'amp-wp-enforced-sizes' );
-
- return $attributes;
- }
-
/**
* Adds or appends key and value to list of attributes
*
diff --git a/includes/sanitizers/class-amp-iframe-sanitizer.php b/includes/sanitizers/class-amp-iframe-sanitizer.php
index 9dac35a8a3e..07c07875f72 100644
--- a/includes/sanitizers/class-amp-iframe-sanitizer.php
+++ b/includes/sanitizers/class-amp-iframe-sanitizer.php
@@ -79,9 +79,11 @@ public function sanitize() {
}
$this->did_convert_elements = true;
-
- $new_attributes = $this->enforce_fixed_height( $new_attributes );
- $new_attributes = $this->enforce_sizes_attribute( $new_attributes );
+ $new_attributes = $this->set_layout( $new_attributes );
+ if ( empty( $new_attributes['layout'] ) && ! empty( $new_attributes['width'] ) && ! empty( $new_attributes['height'] ) ) {
+ $new_attributes['layout'] = 'intrinsic';
+ $this->add_or_append_attribute( $new_attributes, 'class', 'amp-wp-enforced-sizes' );
+ }
$new_node = AMP_DOM_Utils::create_node( $this->dom, 'amp-iframe', $new_attributes );
@@ -126,8 +128,7 @@ public function sanitize() {
* @return array Returns HTML attributes; removes any not specifically declared above from input.
*/
private function filter_attributes( $attributes ) {
- $out = array();
- $out['style'] = 'max-width:100%'; // AMP_Style_Sanitizer will move this to the amp-custom style.
+ $out = array();
foreach ( $attributes as $name => $value ) {
switch ( $name ) {
diff --git a/includes/sanitizers/class-amp-img-sanitizer.php b/includes/sanitizers/class-amp-img-sanitizer.php
index e4a99512dea..e3fa9a878c3 100644
--- a/includes/sanitizers/class-amp-img-sanitizer.php
+++ b/includes/sanitizers/class-amp-img-sanitizer.php
@@ -119,7 +119,6 @@ private function filter_attributes( $attributes ) {
case 'alt':
case 'class':
case 'srcset':
- case 'sizes':
case 'on':
case 'attribution':
$out[ $name ] = $value;
@@ -130,6 +129,10 @@ private function filter_attributes( $attributes ) {
$out[ $name ] = $this->sanitize_dimension( $value, $name );
break;
+ case 'data-amp-layout':
+ $out['layout'] = $value;
+ break;
+
default:
break;
}
@@ -204,7 +207,10 @@ private function adjust_and_replace_nodes_in_array_map( $node_lists ) {
private function adjust_and_replace_node( $node ) {
$old_attributes = AMP_DOM_Utils::get_node_attributes_as_assoc_array( $node );
$new_attributes = $this->filter_attributes( $old_attributes );
- $new_attributes = $this->enforce_sizes_attribute( $new_attributes );
+ $this->add_or_append_attribute( $new_attributes, 'class', 'amp-wp-enforced-sizes' );
+ if ( empty( $new_attributes['layout'] ) && ! empty( $new_attributes['height'] ) && ! empty( $new_attributes['width'] ) ) {
+ $new_attributes['layout'] = 'intrinsic';
+ }
if ( $this->is_gif_url( $new_attributes['src'] ) ) {
$this->did_convert_elements = true;
diff --git a/includes/sanitizers/class-amp-video-sanitizer.php b/includes/sanitizers/class-amp-video-sanitizer.php
index 1dadfcc00eb..0512da17754 100644
--- a/includes/sanitizers/class-amp-video-sanitizer.php
+++ b/includes/sanitizers/class-amp-video-sanitizer.php
@@ -49,9 +49,10 @@ public function sanitize() {
$old_attributes = AMP_DOM_Utils::get_node_attributes_as_assoc_array( $node );
$new_attributes = $this->filter_attributes( $old_attributes );
-
- $new_attributes = $this->enforce_fixed_height( $new_attributes );
- $new_attributes = $this->enforce_sizes_attribute( $new_attributes );
+ $new_attributes = $this->set_layout( $new_attributes );
+ if ( empty( $new_attributes['layout'] ) && ! empty( $new_attributes['width'] ) && ! empty( $new_attributes['height'] ) ) {
+ $new_attributes['layout'] = 'responsive';
+ }
$new_node = AMP_DOM_Utils::create_node( $this->dom, 'amp-video', $new_attributes );
@@ -124,8 +125,7 @@ public function sanitize() {
* @return array Returns HTML attributes; removes any not specifically declared above from input.
*/
private function filter_attributes( $attributes ) {
- $out = array();
- $out['style'] = 'max-width:100%'; // Note that this will get moved to amp-custom style by AMP_Style_Sanitizer.
+ $out = array();
foreach ( $attributes as $name => $value ) {
switch ( $name ) {
diff --git a/tests/test-amp-iframe-sanitizer.php b/tests/test-amp-iframe-sanitizer.php
index d451f4715be..be2f00becfd 100644
--- a/tests/test-amp-iframe-sanitizer.php
+++ b/tests/test-amp-iframe-sanitizer.php
@@ -10,57 +10,57 @@ public function get_data() {
'simple_iframe' => array(
'',
- '',
+ '',
),
'force_https' => array(
'',
- '',
+ '',
),
'iframe_without_dimensions' => array(
'',
- '',
+ '',
),
'iframe_with_height_only' => array(
'',
- '',
+ '',
),
'iframe_with_width_only' => array(
'',
- '',
+ '',
),
'iframe_with_invalid_frameborder' => array(
'',
- '',
+ '',
),
'iframe_with_1_frameborder' => array(
'',
- '',
+ '',
),
'simple_iframe_with_sandbox' => array(
'',
- '',
+ '',
),
'iframe_with_blacklisted_attribute' => array(
'',
- '',
+ '',
),
'iframe_with_sizes_attribute_is_overridden' => array(
- '',
- '',
+ '',
+ '',
),
'iframe_with_protocol_relative_url' => array(
'',
- '',
+ '',
),
'multiple_same_iframe' => array(
@@ -69,7 +69,7 @@ public function get_data() {
',
- '',
+ '',
),
'multiple_different_iframes' => array(
@@ -78,19 +78,19 @@ public function get_data() {
',
- '',
+ '',
),
'iframe_in_p_tag' => array(
'
',
- '',
+ '',
),
'multiple_iframes_in_p_tag' => array(
'',
- '',
+ '',
),
'multiple_iframes_and_contents_in_p_tag' => array(
'contents
',
- 'contents
',
+ 'contents
',
),
);
}
@@ -160,7 +160,7 @@ public function test_get_scripts__did_convert() {
public function test__args__placeholder() {
$source = '';
- $expected = '';
+ $expected = '';
$dom = AMP_DOM_Utils::get_dom_from_content( $source );
$sanitizer = new AMP_Iframe_Sanitizer( $dom, array(
diff --git a/tests/test-amp-img-sanitizer.php b/tests/test-amp-img-sanitizer.php
index c9c02a90633..0f15018618c 100644
--- a/tests/test-amp-img-sanitizer.php
+++ b/tests/test-amp-img-sanitizer.php
@@ -27,6 +27,11 @@ public function get_data() {
'',
),
+ 'image_with_layout' => array(
+ '',
+ '',
+ ),
+
'image_with_spaces_only_src' => array(
'',
'',
@@ -34,77 +39,77 @@ public function get_data() {
'image_with_empty_width_and_height' => array(
'',
- '
',
+ '
',
),
'image_with_empty_width' => array(
'',
- '
',
+ '
',
),
'image_with_empty_height' => array(
'',
- '
',
+ '
',
),
'image_with_zero_width' => array(
'',
- '
',
+ '
',
),
'image_with_zero_width_and_height' => array(
'',
- '
',
+ '
',
),
'image_with_decimal_width' => array(
'',
- '
',
+ '
',
),
'image_with_self_closing_tag' => array(
'',
- '',
+ '',
),
'image_with_no_end_tag' => array(
'',
- '',
+ '',
),
'image_with_end_tag' => array(
'',
- '',
+ '',
),
'image_with_on_attribute' => array(
'',
- '',
+ '',
),
'image_with_blacklisted_attribute' => array(
'',
- '',
+ '',
),
'image_with_no_dimensions_is_forced_dimensions' => array(
'',
- '',
+ '',
),
'image_with_sizes_attribute_is_overridden' => array(
- '',
- '',
+ '',
+ '',
),
'gif_image_conversion' => array(
'',
- '',
+ '',
),
'gif_image_url_with_querystring' => array(
'',
- '',
+ '',
),
'multiple_same_image' => array(
@@ -113,7 +118,7 @@ public function get_data() {
',
- '',
+ '',
),
'multiple_different_images' => array(
@@ -121,7 +126,7 @@ public function get_data() {
',
- '',
+ '',
),
);
}
diff --git a/tests/test-amp-video-sanitizer.php b/tests/test-amp-video-sanitizer.php
index e5cb4308651..5a0f989db05 100644
--- a/tests/test-amp-video-sanitizer.php
+++ b/tests/test-amp-video-sanitizer.php
@@ -10,42 +10,42 @@ public function get_data() {
'simple_video' => array(
'',
- '',
+ '',
),
'video_without_dimensions' => array(
'',
- '',
+ '',
),
'autoplay_attribute' => array(
'',
- '',
+ '',
),
'autoplay_attribute__false' => array(
'',
- '',
+ '',
),
'video_with_whitelisted_attributes__enabled' => array(
'',
- '',
+ '',
),
'video_with_whitelisted_attributes__disabled' => array(
'',
- '',
+ '',
),
'video_with_blacklisted_attribute' => array(
'',
- '',
+ '',
),
'video_with_sizes_attribute_is_overridden' => array(
- '',
- '',
+ '',
+ '',
),
'video_with_children' => array(
@@ -53,7 +53,7 @@ public function get_data() {