Changeset 1708734
- Timestamp:
- 08/05/2017 03:59:01 AM (7 years ago)
- Location:
- amp/trunk
- Files:
-
- 34 added
- 1 deleted
- 31 edited
Legend:
- Unmodified
- Added
- Removed
-
amp/trunk/amp.php
r1514204 r1708734 6 6 * Author: Automattic 7 7 * Author URI: https://automattic.com 8 * Version: 0. 4.28 * Version: 0. 9 9 * Text Domain: amp 10 10 * Domain Path: /languages/ … … 14 14 define( 'AMP__FILE__', __FILE__ ); 15 15 define( 'AMP__DIR__', dirname( __FILE__ ) ); 16 define( 'AMP__VERSION', '0. 4.2' );16 define( 'AMP__VERSION', '0.' ); 17 17 18 18 require_once( AMP__DIR__ . '/back-compat/back-compat.php' ); … … 61 61 add_filter( 'request', 'amp_force_query_var_value' ); 62 62 add_action( 'wp', 'amp_maybe_add_actions' ); 63 64 65 63 66 64 67 if ( class_exists( 'Jetpack' ) && ! ( defined( 'IS_WPCOM' ) && IS_WPCOM ) ) { … … 115 118 require_once( AMP__DIR__ . '/includes/amp-post-template-actions.php' ); 116 119 require_once( AMP__DIR__ . '/includes/amp-post-template-functions.php' ); 120 117 121 } 118 122 … … 122 126 123 127 function amp_render() { 128 129 130 131 132 133 134 135 136 137 138 124 139 amp_load_classes(); 125 140 126 $post_id = get_queried_object_id();127 141 do_action( 'pre_amp_render_post', $post_id ); 128 142 … … 130 144 $template = new AMP_Post_Template( $post_id ); 131 145 $template->load(); 132 exit;133 146 } 134 147 … … 158 171 } 159 172 add_action( 'plugins_loaded', '_amp_bootstrap_customizer', 9 ); 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 -
amp/trunk/includes/admin/class-amp-customizer.php
r1510272 r1708734 47 47 // Our custom panels only need to go for AMP Customizer requests though 48 48 if ( self::is_amp_customizer() ) { 49 if ( empty( $_GET['url'] ) ) { 49 if ( empty( $_GET['url'] ) ) { 50 50 $wp_customize->set_preview_url( amp_admin_get_preview_permalink() ); 51 51 } … … 157 157 158 158 public function force_mobile_preview( $devices ) { 159 if ( isset( $devices[ 'mobile'] ) ) {159 if ( isset( $devices[] ) ) { 160 160 $devices['mobile']['default'] = true; 161 161 unset( $devices['desktop']['default'] ); … … 166 166 167 167 public static function is_amp_customizer() { 168 return ! empty( $_REQUEST[ AMP_CUSTOMIZER_QUERY_VAR ] ); 168 return ! empty( $_REQUEST[ AMP_CUSTOMIZER_QUERY_VAR ] ); 169 169 } 170 170 } -
amp/trunk/includes/admin/functions.php
r1510272 r1708734 1 1 <?php 2 2 // Callbacks for adding AMP-related things to the admin. 3 4 5 3 6 4 7 define( 'AMP_CUSTOMIZER_QUERY_VAR', 'customize_amp' ); … … 23 26 } 24 27 25 /**26 * Registers a submenu page to access the AMP template editor panel in the Customizer.27 */28 function amp_add_customizer_link() {29 // Teensy little hack on menu_slug, but it works. No redirect!30 $menu_slug = add_query_arg( array(31 'autofocus[panel]' => AMP_Template_Customizer::PANEL_ID,32 'return' => rawurlencode( admin_url() ),33 AMP_CUSTOMIZER_QUERY_VAR => true,34 ), 'customize.php' );35 36 // Add the theme page.37 $page = add_theme_page(38 __( 'AMP', 'amp' ),39 __( 'AMP', 'amp' ),40 'edit_theme_options',41 $menu_slug42 );43 }44 45 28 function amp_admin_get_preview_permalink() { 46 29 /** 47 * Filter the post type to retrieve the latest offor use in the AMP template customizer.30 * Filter the post type to retrieve the latest for use in the AMP template customizer. 48 31 * 49 32 * @param string $post_type Post type slug. Default 'post'. … … 70 53 return amp_get_permalink( $post_id ); 71 54 } 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 -
amp/trunk/includes/amp-helper-functions.php
r1510272 r1708734 8 8 } 9 9 10 if ( '' != get_option( 'permalink_structure' ) ) { 10 $structure = get_option( 'permalink_structure' ); 11 if ( empty( $structure ) ) { 12 $amp_url = add_query_arg( AMP_QUERY_VAR, 1, get_permalink( $post_id ) ); 13 } else { 11 14 $amp_url = trailingslashit( get_permalink( $post_id ) ) . user_trailingslashit( AMP_QUERY_VAR, 'single_amp' ); 12 } else {13 $amp_url = add_query_arg( AMP_QUERY_VAR, 1, get_permalink( $post_id ) );14 15 } 15 16 … … 40 41 */ 41 42 function is_amp_endpoint() { 43 44 45 46 42 47 return false !== get_query_var( AMP_QUERY_VAR, false ); 43 48 } -
amp/trunk/includes/amp-post-template-actions.php
r1510272 r1708734 2 2 // Callbacks for adding content to an AMP template 3 3 4 add_action( 'amp_post_template_head', 'amp_post_template_add_title' ); 4 function amp_post_template_init_hooks() { 5 add_action( 'amp_post_template_head', 'amp_post_template_add_title' ); 6 add_action( 'amp_post_template_head', 'amp_post_template_add_canonical' ); 7 add_action( 'amp_post_template_head', 'amp_post_template_add_scripts' ); 8 add_action( 'amp_post_template_head', 'amp_post_template_add_fonts' ); 9 add_action( 'amp_post_template_head', 'amp_post_template_add_boilerplate_css' ); 10 add_action( 'amp_post_template_head', 'amp_post_template_add_schemaorg_metadata' ); 11 add_action( 'amp_post_template_css', 'amp_post_template_add_styles', 99 ); 12 add_action( 'amp_post_template_data', 'amp_post_template_add_analytics_script' ); 13 add_action( 'amp_post_template_footer', 'amp_post_template_add_analytics_data' ); 14 } 15 5 16 function amp_post_template_add_title( $amp_template ) { 6 17 ?> … … 9 20 } 10 21 11 add_action( 'amp_post_template_head', 'amp_post_template_add_canonical' );12 22 function amp_post_template_add_canonical( $amp_template ) { 13 23 ?> … … 16 26 } 17 27 18 add_action( 'amp_post_template_head', 'amp_post_template_add_scripts' );19 28 function amp_post_template_add_scripts( $amp_template ) { 20 29 $scripts = $amp_template->get( 'amp_component_scripts', array() ); 21 foreach ( $scripts as $element => $script ) : ?> 22 <script custom-element="<?php echo esc_attr( $element ); ?>" src="<?php echo esc_url( $script ); ?>" async></script> 30 foreach ( $scripts as $element => $script ) : 31 $custom_type = ($element == 'amp-mustache') ? 'template' : 'element'; ?> 32 <script custom-<?php echo esc_attr( $custom_type ); ?>="<?php echo esc_attr( $element ); ?>" src="<?php echo esc_url( $script ); ?>" async></script> 23 33 <?php endforeach; ?> 24 34 <script src="<?php echo esc_url( $amp_template->get( 'amp_runtime_script' ) ); ?>" async></script> … … 26 36 } 27 37 28 add_action( 'amp_post_template_head', 'amp_post_template_add_fonts' );29 38 function amp_post_template_add_fonts( $amp_template ) { 30 39 $font_urls = $amp_template->get( 'font_urls', array() ); 31 foreach ( $font_urls as $slug => $url ) : ?>40 foreach( $font_urls as $slug => $url ) : ?> 32 41 <link rel="stylesheet" href="<?php echo esc_url( $url ); ?>"> 33 42 <?php endforeach; 34 43 } 35 44 36 add_action( 'amp_post_template_head', 'amp_post_template_add_boilerplate_css' );37 45 function amp_post_template_add_boilerplate_css( $amp_template ) { 38 46 ?> … … 41 49 } 42 50 43 add_action( 'amp_post_template_head', 'amp_post_template_add_schemaorg_metadata' );44 51 function amp_post_template_add_schemaorg_metadata( $amp_template ) { 45 52 $metadata = $amp_template->get( 'metadata' ); … … 48 55 } 49 56 ?> 50 <script type="application/ld+json"><?php echo json_encode( $metadata ); ?></script>57 <script type="application/ld+json"><?php echo json_encode( $metadata ); ?></script> 51 58 <?php 52 59 } 53 60 54 add_action( 'amp_post_template_css', 'amp_post_template_add_styles', 99 );55 61 function amp_post_template_add_styles( $amp_template ) { 56 62 $styles = $amp_template->get( 'post_amp_styles' ); … … 58 64 echo '/* Inline styles */' . PHP_EOL; 59 65 foreach ( $styles as $selector => $declarations ) { 60 $declarations = implode( ";", $declarations ) . ";";66 $declarations = implode( ; 61 67 printf( '%1$s{%2$s}', $selector, $declarations ); 62 68 } … … 64 70 } 65 71 66 add_action( 'amp_post_template_data', 'amp_post_template_add_analytics_script' );67 72 function amp_post_template_add_analytics_script( $data ) { 68 73 if ( ! empty( $data['amp_analytics'] ) ) { … … 72 77 } 73 78 74 add_action( 'amp_post_template_footer', 'amp_post_template_add_analytics_data' );75 79 function amp_post_template_add_analytics_data( $amp_template ) { 76 80 $analytics_entries = $amp_template->get( 'amp_analytics' ); … … 81 85 foreach ( $analytics_entries as $id => $analytics_entry ) { 82 86 if ( ! isset( $analytics_entry['type'], $analytics_entry['attributes'], $analytics_entry['config_data'] ) ) { 83 _doing_it_wrong( __FUNCTION__, sprintf( __( 'Analytics entry for %s is missing one of the following keys: `type`, `attributes`, or `config_data` (array keys: %s)', 'amp' ), esc_html( $id ), esc_html( implode( ', ', array_keys( $analytics_entry ) ) ) ), '0.3.2' );87 _doing_it_wrong( __FUNCTION__, sprintf( __( 'Analytics entry for %s is missing one of the following keys: `type`, `attributes`, or `config_data` (array keys: %s)', 'amp' ), esc_html( $id ), esc_html( implode( ', ', array_keys( $analytics_entry ) ) ) ), '0.3.2' ); 84 88 continue; 85 89 } 86 87 90 $script_element = AMP_HTML_Utils::build_tag( 'script', array( 88 91 'type' => 'application/json', 89 ), json_encode( $analytics_entry['config_data'] ) );92 ), json_encode( $analytics_entry['config_data'] ) ); 90 93 91 94 $amp_analytics_attr = array_merge( array( -
amp/trunk/includes/amp-post-template-functions.php
r1514204 r1708734 9 9 10 10 // 3 or 6 hex digits, or the empty string. 11 if ( preg_match( '|^#([A-Fa-f0-9]{3}){1,2}$|', $color ) ) {11 if ( preg_match('|^#([A-Fa-f0-9]{3}){1,2}$|', $color ) ) { 12 12 return $color; 13 13 } -
amp/trunk/includes/class-amp-content.php
r1514204 r1708734 64 64 65 65 if ( ! is_subclass_of( $embed_handler, 'AMP_Base_Embed_Handler' ) ) { 66 _doing_it_wrong( __METHOD__, sprintf( __( 'Embed Handler (%s) must extend `AMP_Embed_Handler`', 'amp' ), $embed_handler_class ), '0.1' );66 _doing_it_wrong( __METHOD__, sprintf( __( 'Embed Handler (%s) must extend `AMP_Embed_Handler`', 'amp' ), $embed_handler_class ), '0.1' ); 67 67 continue; 68 68 } … … 100 100 foreach ( $sanitizer_classes as $sanitizer_class => $args ) { 101 101 if ( ! class_exists( $sanitizer_class ) ) { 102 _doing_it_wrong( __METHOD__, sprintf( __( 'Sanitizer (%s) class does not exist', 'amp' ), esc_html( $sanitizer_class ) ), '0.4.1' );102 _doing_it_wrong( __METHOD__, sprintf( __( 'Sanitizer (%s) class does not exist', 'amp' ), esc_html( $sanitizer_class ) ), '0.4.1' ); 103 103 continue; 104 104 } … … 107 107 108 108 if ( ! is_subclass_of( $sanitizer, 'AMP_Base_Sanitizer' ) ) { 109 _doing_it_wrong( __METHOD__, sprintf( __( 'Sanitizer (%s) must extend `AMP_Base_Sanitizer`', 'amp' ), esc_html( $sanitizer_class ) ), '0.1' );109 _doing_it_wrong( __METHOD__, sprintf( __( 'Sanitizer (%s) must extend `AMP_Base_Sanitizer`', 'amp' ), esc_html( $sanitizer_class ) ), '0.1' ); 110 110 continue; 111 111 } -
amp/trunk/includes/class-amp-post-template.php
r1514204 r1708734 4 4 require_once( AMP__DIR__ . '/includes/utils/class-amp-html-utils.php' ); 5 5 require_once( AMP__DIR__ . '/includes/utils/class-amp-string-utils.php' ); 6 6 7 7 8 require_once( AMP__DIR__ . '/includes/class-amp-content.php' ); … … 9 10 require_once( AMP__DIR__ . '/includes/sanitizers/class-amp-style-sanitizer.php' ); 10 11 require_once( AMP__DIR__ . '/includes/sanitizers/class-amp-blacklist-sanitizer.php' ); 12 11 13 require_once( AMP__DIR__ . '/includes/sanitizers/class-amp-img-sanitizer.php' ); 12 14 require_once( AMP__DIR__ . '/includes/sanitizers/class-amp-video-sanitizer.php' ); 13 15 require_once( AMP__DIR__ . '/includes/sanitizers/class-amp-iframe-sanitizer.php' ); 14 16 require_once( AMP__DIR__ . '/includes/sanitizers/class-amp-audio-sanitizer.php' ); 17 15 18 16 19 require_once( AMP__DIR__ . '/includes/embeds/class-amp-twitter-embed.php' ); 17 20 require_once( AMP__DIR__ . '/includes/embeds/class-amp-youtube-embed.php' ); 21 22 23 18 24 require_once( AMP__DIR__ . '/includes/embeds/class-amp-gallery-embed.php' ); 19 25 require_once( AMP__DIR__ . '/includes/embeds/class-amp-instagram-embed.php' ); 20 26 require_once( AMP__DIR__ . '/includes/embeds/class-amp-vine-embed.php' ); 21 27 require_once( AMP__DIR__ . '/includes/embeds/class-amp-facebook-embed.php' ); 28 22 29 23 30 class AMP_Post_Template { … … 70 77 'merriweather' => 'https://fonts.googleapis.com/css?family=Merriweather:400,400italic,700,700italic', 71 78 ), 79 80 72 81 73 82 /** … … 82 91 */ 83 92 'amp_analytics' => apply_filters( 'amp_post_template_analytics', array(), $this->post ), 84 93 ); 85 94 86 95 $this->build_post_content(); … … 96 105 return $this->data[ $property ]; 97 106 } else { 98 _doing_it_wrong( __METHOD__, sprintf( __( 'Called for non-existant key ("%s").', 'amp' ), esc_html( $property ) ), '0.1' );107 _doing_it_wrong( __METHOD__, sprintf( __( 'Called for non-existant key ("%s").', 'amp' ), esc_html( $property ) ), '0.1' ); 99 108 } 100 109 … … 224 233 'AMP_Twitter_Embed_Handler' => array(), 225 234 'AMP_YouTube_Embed_Handler' => array(), 235 236 237 226 238 'AMP_Instagram_Embed_Handler' => array(), 227 239 'AMP_Vine_Embed_Handler' => array(), 228 240 'AMP_Facebook_Embed_Handler' => array(), 241 229 242 'AMP_Gallery_Embed_Handler' => array(), 230 243 ), $this->post ), 231 244 apply_filters( 'amp_content_sanitizers', array( 232 245 'AMP_Style_Sanitizer' => array(), 233 'AMP_Blacklist_Sanitizer' => array(),246 'AMP_Blacklist_Sanitizer' => array(), 234 247 'AMP_Img_Sanitizer' => array(), 235 248 'AMP_Video_Sanitizer' => array(), 236 249 'AMP_Audio_Sanitizer' => array(), 250 237 251 'AMP_Iframe_Sanitizer' => array( 238 252 'add_placeholder' => true, 239 253 ), 254 240 255 ), $this->post ), 241 256 array( … … 246 261 $this->add_data_by_key( 'post_amp_content', $amp_content->get_amp_content() ); 247 262 $this->merge_data_for_key( 'amp_component_scripts', $amp_content->get_amp_scripts() ); 248 $this-> add_data_by_key( 'post_amp_styles', $amp_content->get_amp_styles() );263 $this->_key( 'post_amp_styles', $amp_content->get_amp_styles() ); 249 264 } 250 265 … … 275 290 array( 'AMP_Img_Sanitizer' => array() ), 276 291 array( 277 'content_max_width' => $this->get( 'content_max_width' ) 292 'content_max_width' => $this->get( 'content_max_width' ) 278 293 ) 279 294 ); … … 289 304 290 305 if ( $featured_styles ) { 291 $this-> add_data_by_key( 'post_amp_styles', $featured_styles );306 $this->_key( 'post_amp_styles', $featured_styles ); 292 307 } 293 308 } … … 382 397 $file = apply_filters( 'amp_post_template_file', $file, $template_type, $this->post ); 383 398 if ( ! $this->is_valid_template( $file ) ) { 384 _doing_it_wrong( __METHOD__, sprintf( __( 'Path validation for template (%s) failed. Path cannot traverse and must be located in `%s`.', 'amp' ), esc_html( $file ), 'WP_CONTENT_DIR' ), '0.1' );399 _doing_it_wrong( __METHOD__, sprintf( __( 'Path validation for template (%s) failed. Path cannot traverse and must be located in `%s`.', 'amp' ), esc_html( $file ), 'WP_CONTENT_DIR' ), '0.1' ); 385 400 return; 386 401 } -
amp/trunk/includes/embeds/class-amp-gallery-embed.php
r1364370 r1708734 40 40 'include' => '', 41 41 'exclude' => '', 42 'size' => array( $this->args['width'], $this->args['height'] ) 42 'size' => array( $this->args['width'], $this->args['height'] ) 43 43 ), $attr, 'gallery' ); 44 44 -
amp/trunk/includes/embeds/class-amp-instagram-embed.php
r1478266 r1708734 53 53 54 54 public function oembed( $matches, $attr, $url, $rawattr ) { 55 return $this->render( array( 'url' => $url, 'instagram_id' => 55 return $this->render( array( 'url' => $url, 'instagram_id' => end( $matches ) ) ); 56 56 } 57 57 -
amp/trunk/includes/embeds/class-amp-vine-embed.php
r1337793 r1708734 29 29 30 30 public function oembed( $matches, $attr, $url, $rawattr ) { 31 return $this->render( array( 'url' => $url, 'vine_id' => 31 return $this->render( array( 'url' => $url, 'vine_id' => end( $matches ) ) ); 32 32 } 33 33 -
amp/trunk/includes/embeds/class-amp-youtube-embed.php
r1510272 r1708734 49 49 if ( isset( $attr[0] ) ) { 50 50 $url = ltrim( $attr[0] , '=' ); 51 } elseif ( function_exists 51 } elseif ( function_exists( 'shortcode_new_to_old_params' ) ) { 52 52 $url = shortcode_new_to_old_params( $attr ); 53 53 } … … 93 93 private function get_video_id_from_url( $url ) { 94 94 $video_id = false; 95 $parsed_url = parse_url( $url );95 $parsed_url = parse_url( $url ); 96 96 97 97 if ( self::SHORT_URL_HOST === substr( $parsed_url['host'], -strlen( self::SHORT_URL_HOST ) ) ) { … … 114 114 $parts = explode( '/', $parsed_url['path'] ); 115 115 116 if ( in_array( $parts[1], array( 'v', 'e', 'embed' ) ) ) {116 if ( in_array( $parts[1], array( 'v', 'e', 'embed' ) ) ) { 117 117 $video_id = $parts[2]; 118 118 } -
amp/trunk/includes/sanitizers/class-amp-base-sanitizer.php
r1510272 r1708734 43 43 44 44 if ( AMP_String_Utils::endswith( $value, '%' ) ) { 45 if ( 'width' === $dimension && isset( $this->args[ 45 if ( 'width' === $dimension && isset( $this->args['content_max_width'] ) ) { 46 46 $percentage = absint( $value ) / 100; 47 return round( $percentage * $this->args[ 47 return round( $percentage * $this->args['content_max_width'] ); 48 48 } 49 49 } -
amp/trunk/includes/sanitizers/class-amp-blacklist-sanitizer.php
r1510272 r1708734 8 8 * See following for blacklist: 9 9 * https://github.com/ampproject/amphtml/blob/master/spec/amp-html-format.md#html-tags 10 11 12 10 13 */ 11 14 class AMP_Blacklist_Sanitizer extends AMP_Base_Sanitizer { … … 29 32 30 33 private function strip_attributes_recursive( $node, $bad_attributes, $bad_protocols ) { 31 if ( $node->nodeType !== XML_ELEMENT_NODE) {34 if ( ) { 32 35 return; 33 36 } … … 37 40 // Some nodes may contain valid content but are themselves invalid. 38 41 // Remove the node but preserve the children. 39 42 if ( 'font' === $node_name ) { 40 43 $this->replace_node_with_children( $node, $bad_attributes, $bad_protocols ); 41 44 return; … … 50 53 $attribute = $node->attributes->item( $i ); 51 54 $attribute_name = strtolower( $attribute->name ); 52 if ( in_array( $attribute_name, $bad_attributes ) ) {55 if ( in_array( $attribute_name, $bad_attributes ) ) { 53 56 $node->removeAttribute( $attribute_name ); 54 57 continue; … … 56 59 57 60 // on* attributes (like onclick) are a special case 58 if ( 0 === stripos( $attribute_name, 'on' ) && $attribute_name != 'on') {61 if ( 0 === stripos( $attribute_name, 'on' ) && ) { 59 62 $node->removeAttribute( $attribute_name ); 60 63 continue; … … 125 128 $href = $node->getAttribute( 'href' ); 126 129 127 // If no href is set and this isn't an anchor, it's invalid128 130 if ( empty( $href ) ) { 129 $name_attr = $node->getAttribute( 'name' ); 130 if ( ! empty( $name_attr ) ) { 131 // No further validation is required 132 return true; 133 } else { 134 return false; 135 } 131 // If no href, check that a is an anchor or not. 132 // We don't need to validate anchors any further. 133 return $node->hasAttribute( 'name' ) || $node->hasAttribute( 'id' ); 136 134 } 137 135 … … 151 149 152 150 if ( false === filter_var( $href, FILTER_VALIDATE_URL ) 153 && ! in_array( $protocol, $special_protocols ) ) {151 && ! in_array( $protocol, $special_protocols ) ) { 154 152 return false; 155 153 } 156 154 157 if ( ! in_array( $protocol, $valid_protocols ) ) {155 if ( ! in_array( $protocol, $valid_protocols ) ) { 158 156 return false; 159 157 } -
amp/trunk/includes/sanitizers/class-amp-iframe-sanitizer.php
r1478266 r1708734 98 98 break; 99 99 100 101 100 case 'frameborder': 102 101 if ( '0' !== $value && '1' !== $value ) { … … 118 117 } 119 118 120 if ( ! isset( $out[ 'sandbox'] ) ) {121 $out[ 'sandbox'] = self::SANDBOX_DEFAULTS;119 if ( ! isset( $out[] ) ) { 120 $out[] = self::SANDBOX_DEFAULTS; 122 121 } 123 122 -
amp/trunk/includes/sanitizers/class-amp-img-sanitizer.php
r1510272 r1708734 19 19 20 20 public function sanitize() { 21 21 22 $nodes = $this->dom->getElementsByTagName( self::$tag ); 23 24 22 25 $num_nodes = $nodes->length; 26 23 27 if ( 0 === $num_nodes ) { 24 28 return; … … 27 31 for ( $i = $num_nodes - 1; $i >= 0; $i-- ) { 28 32 $node = $nodes->item( $i ); 29 $old_attributes = AMP_DOM_Utils::get_node_attributes_as_assoc_array( $node );30 33 31 if ( empty( $old_attributes['src']) ) {34 if ( ) ) { 32 35 $node->parentNode->removeChild( $node ); 33 36 continue; 34 37 } 35 38 36 $new_attributes = $this->filter_attributes( $old_attributes ); 39 // Determine which images need their dimensions determined/extracted. 40 if ( '' === $node->getAttribute( 'width' ) || '' === $node->getAttribute( 'height' ) ) { 41 $need_dimensions[ $node->getAttribute( 'src' ) ][] = $node; 42 } else { 43 $this->adjust_and_replace_node( $node ); 44 } 45 } 37 46 38 // Try to extract dimensions for the image, if not set. 39 if ( ! isset( $new_attributes['width'] ) || ! isset( $new_attributes['height'] ) ) { 40 $dimensions = AMP_Image_Dimension_Extractor::extract( $new_attributes['src'] ); 41 if ( is_array( $dimensions ) ) { 42 $new_attributes['width'] = $dimensions[0]; 43 $new_attributes['height'] = $dimensions[1]; 47 $this->determine_dimensions( $need_dimensions ); 48 $this->adjust_and_replace_nodes_in_array_map( $need_dimensions ); 49 } 50 51 /** 52 * Figure out width and height attribute values for images that don't have them by 53 * attempting to determine actual dimensions and setting reasonable defaults otherwise. 54 * 55 * @param array $need_dimensions List of Img src url to node mappings corresponding to images that need dimensions. 56 */ 57 private function determine_dimensions( $need_dimensions ) { 58 $dimensions_by_url = AMP_Image_Dimension_Extractor::extract( array_keys( $need_dimensions ) ); 59 60 foreach ( $dimensions_by_url as $url => $dimensions ) { 61 foreach ( $need_dimensions[ $url ] as $node ) { 62 // Provide default dimensions for images whose dimensions we couldn't fetch. 63 if ( false === $dimensions ) { 64 $width = isset( $this->args['content_max_width'] ) ? $this->args['content_max_width'] : self::FALLBACK_WIDTH; 65 $height = self::FALLBACK_HEIGHT; 66 $node->setAttribute( 'width', $width ); 67 $node->setAttribute( 'height', $height ); 68 $class = $node->hasAttribute( 'class' ) ? $node->getAttribute( 'class' ) . ' amp-wp-unknown-size' : 'amp-wp-unknown-size'; 69 $node->setAttribute( 'class', $class ); 70 } else { 71 $node->setAttribute( 'width', $dimensions['width'] ); 72 $node->setAttribute( 'height', $dimensions['height'] ); 44 73 } 45 74 } 75 76 46 77 47 // Final fallback when we have no dimensions. 48 if ( ! isset( $new_attributes['width'] ) || ! isset( $new_attributes['height'] ) ) { 49 $new_attributes['width'] = isset( $this->args['content_max_width'] ) ? $this->args['content_max_width'] : self::FALLBACK_WIDTH; 50 $new_attributes['height'] = self::FALLBACK_HEIGHT; 78 /** 79 * Make final modifications to DOMNode 80 * 81 * @param DOMNode $node The DOMNode to adjust and replace 82 */ 83 private function adjust_and_replace_node( $node ) { 84 $old_attributes = AMP_DOM_Utils::get_node_attributes_as_assoc_array( $node ); 85 $new_attributes = $this->filter_attributes( $old_attributes ); 86 $new_attributes = $this->enforce_sizes_attribute( $new_attributes ); 87 if ( $this->is_gif_url( $new_attributes['src'] ) ) { 88 $this->did_convert_elements = true; 89 $new_tag = 'amp-anim'; 90 } else { 91 $new_tag = 'amp-img'; 92 } 93 $new_node = AMP_DOM_Utils::create_node( $this->dom, $new_tag, $new_attributes ); 94 $node->parentNode->replaceChild( $new_node, $node ); 95 } 51 96 52 $this->add_or_append_attribute( $new_attributes, 'class', 'amp-wp-unknown-size' ); 97 /** 98 * Now that all images have width and height attributes, make final tweaks and replace original image nodes 99 * 100 * @param array $node_lists Img DOM nodes (now with width and height attributes). 101 */ 102 private function adjust_and_replace_nodes_in_array_map( $node_lists ) { 103 foreach ( $node_lists as $node_list ) { 104 foreach ( $node_list as $node ) { 105 $this->adjust_and_replace_node( $node ); 53 106 } 54 55 $new_attributes = $this->enforce_sizes_attribute( $new_attributes );56 57 if ( $this->is_gif_url( $new_attributes['src'] ) ) {58 $this->did_convert_elements = true;59 $new_tag = 'amp-anim';60 } else {61 $new_tag = 'amp-img';62 }63 64 $new_node = AMP_DOM_Utils::create_node( $this->dom, $new_tag, $new_attributes );65 $node->parentNode->replaceChild( $new_node, $node );66 107 } 67 108 } … … 104 145 private function is_gif_url( $url ) { 105 146 $ext = self::$anim_extension; 106 $path = parse_url( $url, PHP_URL_PATH );107 return $ext === substr( $path, -strlen( $ext ) );147 $path = parse_url( $url, PHP_URL_PATH ); 148 return ; 108 149 } 109 150 } -
amp/trunk/includes/sanitizers/class-amp-style-sanitizer.php
r1512429 r1708734 19 19 20 20 private function collect_styles_recursive( $node ) { 21 if ( $node->nodeType !== XML_ELEMENT_NODE) {21 if ( ) { 22 22 return; 23 23 } … … 57 57 } 58 58 59 // Normalize order 60 $styles = array_map( 'trim', explode( ';', $string ) ); 59 // safecss returns a string but we want individual rules. 60 // Using preg_split to break up rules by `;` but only if the semi-colon is not inside parens (like a data-encoded image). 61 $styles = array_map( 'trim', preg_split( "/;(?![^(]*\))/", $string ) ); 62 63 // Normalize the order of the styles 61 64 sort( $styles ); 62 65 -
amp/trunk/includes/sanitizers/class-amp-video-sanitizer.php
r1478266 r1708734 10 10 11 11 public static $tag = 'video'; 12 13 14 15 16 17 18 19 20 21 22 12 23 13 24 public function sanitize() { … … 51 62 $node->parentNode->replaceChild( $new_node, $node ); 52 63 } 64 65 53 66 } 54 67 } -
amp/trunk/includes/settings/class-amp-customizer-design-settings.php
r1510272 r1708734 24 24 'default' => self::DEFAULT_HEADER_COLOR, 25 25 'sanitize_callback' => 'sanitize_hex_color', 26 'transport' => 'postMessage' 26 'transport' => 'postMessage' 27 27 ) ); 28 28 … … 32 32 'default' => self::DEFAULT_HEADER_BACKGROUND_COLOR, 33 33 'sanitize_callback' => 'sanitize_hex_color', 34 'transport' => 'postMessage' 34 'transport' => 'postMessage' 35 35 ) ); 36 36 … … 40 40 'default' => self::DEFAULT_COLOR_SCHEME, 41 41 'sanitize_callback' => array( __CLASS__ , 'sanitize_color_scheme' ), 42 'transport' => 'postMessage' 42 'transport' => 'postMessage' 43 43 ) ); 44 44 } 45 45 46 public function register_customizer_ui( $wp_customize ) {46 public function register_customizer_ui( $wp_customize ) { 47 47 $wp_customize->add_section( 'amp_design', array( 48 48 'title' => __( 'Design', 'amp' ), … … 56 56 'label' => __( 'Header Text Color', 'amp' ), 57 57 'section' => 'amp_design', 58 'priority' => 10 58 'priority' => 10 59 59 ) ) 60 60 ); … … 66 66 'label' => __( 'Header Background & Link Color', 'amp' ), 67 67 'section' => 'amp_design', 68 'priority' => 20 68 'priority' => 20 69 69 ) ) 70 70 ); … … 110 110 protected static function get_color_scheme_names() { 111 111 return array( 112 'light' => __( 'Light', 'amp' ),112 'light' => __( 'Light', 'amp'), 113 113 'dark' => __( 'Dark', 'amp' ), 114 114 ); … … 130 130 'muted_text_color' => '#b1b1b1', 131 131 'border_color' => '#707070', 132 ) 132 ) 133 133 ); 134 134 } … … 148 148 $scheme_slugs = array_keys( $schemes ); 149 149 150 if ( ! in_array( $value, $scheme_slugs ) ) {150 if ( ! in_array( $value, $scheme_slugs ) ) { 151 151 $value = self::DEFAULT_COLOR_SCHEME; 152 152 } -
amp/trunk/includes/utils/class-amp-dom-utils.php
r1514204 r1708734 96 96 // Not all are valid AMP, but we include them for completeness. 97 97 $self_closing_tags = array( 98 'area', 'base', 'basefont', 'bgsound', 'br', 'col', 'embed', 'frame', 'hr', 'img', 'input', 'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr', 98 'area', 99 'base', 100 'basefont', 101 'bgsound', 102 'br', 103 'col', 104 'embed', 105 'frame', 106 'hr', 107 'img', 108 'input', 109 'keygen', 110 'link', 111 'meta', 112 'param', 113 'source', 114 'track', 115 'wbr', 99 116 ); 100 117 } 101 118 102 return in_array( $tag, $self_closing_tags );119 return in_array( $tag, $self_closing_tags ); 103 120 } 104 121 } -
amp/trunk/includes/utils/class-amp-html-utils.php
r1337793 r1708734 18 18 return implode( ' ', $string ); 19 19 } 20 21 22 23 24 25 26 27 28 29 30 31 20 32 } -
amp/trunk/includes/utils/class-amp-image-dimension-extractor.php
r1357059 r1708734 3 3 class AMP_Image_Dimension_Extractor { 4 4 static $callbacks_registered = false; 5 6 static public function extract( $url ) { 5 const STATUS_FAILED_LAST_ATTEMPT = 'failed'; 6 const STATUS_IMAGE_EXTRACTION_FAILED = 'failed'; 7 8 static public function extract( $urls ) { 7 9 if ( ! self::$callbacks_registered ) { 8 10 self::register_callbacks(); 9 11 } 10 12 11 $url = self::normalize_url( $url ); 12 if ( false === $url ) { 13 return false; 14 } 15 16 return apply_filters( 'amp_extract_image_dimensions', false, $url ); 13 $valid_urls = array(); 14 foreach ( $urls as $url ) { 15 $url = self::normalize_url( $url ); 16 if ( false !== $url ) { 17 $valid_urls[] = $url; 18 } 19 } 20 21 $dimensions = array_fill_keys( $valid_urls, false ); 22 $dimensions = apply_filters( 'amp_extract_image_dimensions_batch', $dimensions ); 23 24 return $dimensions; 17 25 } 18 26 … … 30 38 } 31 39 32 $parsed = parse_url( $url );40 $parsed = parse_url( $url ); 33 41 if ( ! isset( $parsed['host'] ) ) { 34 42 $path = ''; … … 48 56 self::$callbacks_registered = true; 49 57 50 add_filter( 'amp_extract_image_dimensions', array( __CLASS__, 'extract_from_attachment_metadata' ), 10, 2 ); 51 add_filter( 'amp_extract_image_dimensions', array( __CLASS__, 'extract_by_downloading_image' ), 999, 2 ); // Run really late since this is our last resort 52 53 do_action( 'amp_extract_image_dimensions_callbacks_registered' ); 54 } 55 56 public static function extract_from_attachment_metadata( $dimensions, $url ) { 57 if ( is_array( $dimensions ) ) { 58 return $dimensions; 59 } 60 61 $url = strtok( $url, '?' ); 62 $attachment_id = attachment_url_to_postid( $url ); 63 if ( empty( $attachment_id ) ) { 64 return false; 65 } 66 67 $metadata = wp_get_attachment_metadata( $attachment_id ); 68 if ( ! $metadata ) { 69 return false; 70 } 71 72 return array( $metadata['width'], $metadata['height'] ); 73 } 74 75 public static function extract_by_downloading_image( $dimensions, $url ) { 76 if ( is_array( $dimensions ) ) { 77 return $dimensions; 78 } 79 80 $url_hash = md5( $url ); 81 $transient_name = sprintf( 'amp_img_%s', $url_hash ); 82 $transient_expiry = 30 * DAY_IN_SECONDS; 83 $transient_fail = 'fail'; 84 85 $dimensions = get_transient( $transient_name ); 86 87 if ( is_array( $dimensions ) ) { 88 return $dimensions; 89 } elseif ( $transient_fail === $dimensions ) { 90 return false; 91 } 92 93 // Very simple lock to prevent stampedes 94 $transient_lock_name = sprintf( 'amp_lock_%s', $url_hash ); 95 if ( false !== get_transient( $transient_lock_name ) ) { 96 return false; 97 } 98 set_transient( $transient_lock_name, 1, MINUTE_IN_SECONDS ); 99 100 // Note to other developers: please don't use this class directly as it may not stick around forever... 58 add_filter( 'amp_extract_image_dimensions_batch', array( __CLASS__, 'extract_by_downloading_images' ), 999, 1 ); 59 60 do_action( 'amp_extract_image_dimensions_batch_callbacks_registered' ); 61 } 62 63 /** 64 * Extract dimensions from downloaded images (or transient/cached dimensions from downloaded images) 65 * 66 * @param array $dimensions Image urls mapped to dimensions. 67 * @param string $mode Whether image dimensions should be extracted concurrently or synchronously. 68 * @return array Dimensions mapped to image urls, or false if they could not be retrieved 69 */ 70 public static function extract_by_downloading_images( $dimensions, $mode = 'concurrent' ) { 71 $transient_expiration = 30 * DAY_IN_SECONDS; 72 73 $urls_to_fetch = array(); 74 $images = array(); 75 76 self::determine_which_images_to_fetch( $dimensions, $urls_to_fetch ); 77 self::fetch_images( $urls_to_fetch, $images, $mode ); 78 self::process_fetched_images( $urls_to_fetch, $images, $dimensions, $transient_expiration ); 79 80 return $dimensions; 81 } 82 83 /** 84 * Determine which images to fetch by checking for dimensions in transient/cache. 85 * Creates a short lived transient that acts as a semaphore so that another visitor 86 * doesn't trigger a remote fetch for the same image at the same time. 87 * 88 * @param array $dimensions Image urls mapped to dimensions. 89 * @param array $urls_to_fetch Urls of images to fetch because dimensions are not in transient/cache. 90 */ 91 private static function determine_which_images_to_fetch( &$dimensions, &$urls_to_fetch ) { 92 foreach ( $dimensions as $url => $value ) { 93 94 // Check whether some other callback attached to the filter already provided dimensions for this image. 95 if ( is_array( $value ) ) { 96 continue; 97 } 98 99 $url_hash = md5( $url ); 100 $transient_name = sprintf( 'amp_img_%s', $url_hash ); 101 $cached_dimensions = get_transient( $transient_name ); 102 103 // If we're able to retrieve the dimensions from a transient, set them and move on. 104 if ( is_array( $cached_dimensions ) ) { 105 $dimensions[ $url ] = array( 106 'width' => $cached_dimensions[0], 107 'height' => $cached_dimensions[1], 108 ); 109 continue; 110 } 111 112 // If the value in the transient reflects we couldn't get dimensions for this image the last time we tried, move on. 113 if ( self::STATUS_FAILED_LAST_ATTEMPT === $cached_dimensions ) { 114 $dimensions[ $url ] = false; 115 continue; 116 } 117 118 $transient_lock_name = sprintf( 'amp_lock_%s', $url_hash ); 119 120 // If somebody is already trying to extract dimensions for this transient right now, move on. 121 if ( false !== get_transient( $transient_lock_name ) ) { 122 $dimensions[ $url ] = false; 123 continue; 124 } 125 126 // Include the image as a url to fetch. 127 $urls_to_fetch[ $url ] = array(); 128 $urls_to_fetch[ $url ]['url'] = $url; 129 $urls_to_fetch[ $url ]['transient_name'] = $transient_name; 130 $urls_to_fetch[ $url ]['transient_lock_name'] = $transient_lock_name; 131 set_transient( $transient_lock_name, 1, MINUTE_IN_SECONDS ); 132 } 133 } 134 135 /** 136 * Fetch dimensions of remote images 137 * 138 * @param array $urls_to_fetch Image src urls to fetch. 139 * @param array $images Array to populate with results of image/dimension inspection. 140 * @param string $mode Whether image dimensions should be extracted concurrently or synchronously. 141 */ 142 private static function fetch_images( $urls_to_fetch, &$images, $mode ) { 143 // Use FasterImage when for compatible PHP versions 144 if ( 'synchronous' === $mode || 145 false === function_exists( 'curl_multi_exec' ) || 146 version_compare( PHP_VERSION, '5.4.0' ) < 0 147 ) { 148 self::fetch_images_via_fast_image( $urls_to_fetch, $images ); 149 } else { 150 self::fetch_images_via_faster_image( $urls_to_fetch, $images ); 151 } 152 } 153 154 /** 155 * Fetch images via FastImage library 156 * 157 * @param array $urls_to_fetch Image src urls to fetch. 158 * @param array $images Array to populate with results of image/dimension inspection. 159 */ 160 private static function fetch_images_via_fast_image( $urls_to_fetch, &$images ) { 101 161 if ( ! class_exists( 'FastImage' ) ) { 102 require_once( AMP__DIR__ . '/includes/lib/class-fastimage.php' ); 103 } 104 105 // TODO: look into using curl+stream (https://github.com/willwashburn/FasterImage) 106 $image = new FastImage( $url ); 107 $dimensions = $image->getSize(); 108 109 if ( ! is_array( $dimensions ) ) { 110 set_transient( $transient_name, $transient_fail, $transient_expiry ); 111 delete_transient( $transient_lock_name ); 112 return false; 113 } 114 115 set_transient( $transient_name, $dimensions, $transient_expiry ); 116 delete_transient( $transient_lock_name ); 117 return $dimensions; 162 require_once( AMP__DIR__ . '/includes/lib/fastimage/class-fastimage.php' ); 163 } 164 165 $image = new FastImage(); 166 $urls = array_keys( $urls_to_fetch ); 167 168 foreach ( $urls as $url ) { 169 $result = $image->load( $url ); 170 if ( false === $result ) { 171 $images[ $url ]['size'] = self::STATUS_IMAGE_EXTRACTION_FAILED; 172 } else { 173 $size = $image->getSize(); 174 $images[ $url ]['size'] = $size; 175 } 176 } 177 } 178 179 /** 180 * Fetch images via FasterImage library 181 * 182 * @param array $urls_to_fetch Image src urls to fetch. 183 * @param array $images Array to populate with results of image/dimension inspection. 184 */ 185 private static function fetch_images_via_faster_image( $urls_to_fetch, &$images ) { 186 $urls = array_keys( $urls_to_fetch ); 187 188 if ( ! function_exists( 'amp_get_fasterimage_client' ) ) { 189 require_once( AMP__DIR__ . '/includes/lib/fasterimage/amp-fasterimage.php' ); 190 } 191 192 $user_agent = apply_filters( 'amp_extract_image_dimensions_get_user_agent', self::get_default_user_agent() ); 193 $client = amp_get_fasterimage_client( $user_agent ); 194 $images = $client->batch( $urls ); 195 } 196 197 /** 198 * Determine success or failure of remote fetch, integrate fetched dimensions into url to dimension mapping, 199 * cache fetched dimensions via transient and release/delete semaphore transient 200 * 201 * @param array $urls_to_fetch List of image urls that were fetched and transient names corresponding to each (for unlocking semaphore, setting "real" transient). 202 * @param array $images Results of remote fetch mapping fetched image url to dimensions. 203 * @param array $dimensions Map of image url to dimensions to be updated with results of remote fetch. 204 * @param int $transient_expiration Duration image dimensions should exist in transient/cache. 205 */ 206 private static function process_fetched_images( $urls_to_fetch, $images, &$dimensions, $transient_expiration ) { 207 foreach ( $urls_to_fetch as $url_data ) { 208 $image_data = $images[ $url_data['url'] ]; 209 if ( self::STATUS_IMAGE_EXTRACTION_FAILED === $image_data['size'] ) { 210 $dimensions[ $url_data['url'] ] = false; 211 set_transient( $url_data['transient_name'], self::STATUS_FAILED_LAST_ATTEMPT, $transient_expiration ); 212 } else { 213 $dimensions[ $url_data['url'] ] = array( 214 'width' => $image_data['size'][0], 215 'height' => $image_data['size'][1], 216 ); 217 set_transient( 218 $url_data['transient_name'], 219 array( 220 $image_data['size'][0], 221 $image_data['size'][1], 222 ), 223 $transient_expiration 224 ); 225 } 226 delete_transient( $url_data['transient_lock_name'] ); 227 } 228 } 229 230 231 /** 232 * Get default user agent 233 * 234 * @return string 235 */ 236 public static function get_default_user_agent() { 237 return 'amp-wp, v' . AMP__VERSION . ', ' . get_site_url(); 118 238 } 119 239 } -
amp/trunk/includes/utils/class-amp-string-utils.php
r1478266 r1708734 5 5 return '' !== $haystack 6 6 && '' !== $needle 7 && $needle === substr( $haystack, -strlen( $needle ) );7 && ; 8 8 } 9 9 } -
amp/trunk/jetpack-helper.php
r1364370 r1708734 57 57 $tz = get_option( 'gmt_offset' ); 58 58 $v = 'ext'; 59 $blog_url = parse_url( site_url() );59 $blog_url = parse_url( site_url() ); 60 60 $srv = $blog_url['host']; 61 61 $j = sprintf( '%s:%s', JETPACK__API_VERSION, JETPACK__VERSION ); … … 64 64 } 65 65 66 $data['host'] = rawurlencode( $_SERVER['HTTP_HOST'] );66 $data['host'] = 67 67 $data['rand'] = 'RANDOM'; // amp placeholder 68 68 $data['ref'] = 'DOCUMENT_REFERRER'; // amp placeholder -
amp/trunk/readme.md
r1514204 r1708734 5 5 This plugin adds support for the [Accelerated Mobile Pages](https://www.ampproject.org) (AMP) Project, which is an open source initiative that aims to provide mobile optimized content that can load instantly everywhere. 6 6 7 With the plugin active, all posts on your site will have dynamically generated AMP-compatible versions, accessible by appending `/amp/` to the end your post URLs. For example, if your post URL is `http://example.com/2016/01/01/amp-on/`, you can access the AMP version at `http://example.com/2016/01/01/amp-on/amp/`. If you do not have [pretty permalinks](https://codex.wordpress.org/Using_Permalinks#mod_rewrite:_.22Pretty_Permalinks.22) enabled, you can do the same thing by appending `?amp=1`, i.e. `http://example.com/ 2016/01/01/amp-on/?amp=1`7 With the plugin active, all posts on your site will have dynamically generated AMP-compatible versions, accessible by appending `/amp/` to the end your post URLs. For example, if your post URL is `http://example.com/2016/01/01/amp-on/`, you can access the AMP version at `http://example.com/2016/01/01/amp-on/amp/`. If you do not have [pretty permalinks](https://codex.wordpress.org/Using_Permalinks#mod_rewrite:_.22Pretty_Permalinks.22) enabled, you can do the same thing by appending `?amp=1`, i.e. `http://example.com/amp=1` 8 8 9 9 Note #1: that Pages and archives are not currently supported. … … 54 54 #### Logo Only 55 55 56 If you want to hide the site text and just show a logo, use the `amp_post_template_css` action. The following colo urs the title bar black, hides the site title, and replaces it with a centered logo:57 58 ``` 56 If you want to hide the site text and just show a logo, use the `amp_post_template_css` action. The following colors the title bar black, hides the site title, and replaces it with a centered logo: 57 58 ``` 59 59 add_action( 'amp_post_template_css', 'xyz_amp_additional_css_styles' ); 60 60 … … 62 62 // only CSS here please... 63 63 ?> 64 nav.amp-wp-title-bar {64 r { 65 65 padding: 12px 0; 66 66 background: #000; 67 67 } 68 nav.amp-wp-title-bar a {68 r a { 69 69 background-image: url( 'https://example.com/path/to/logo.png' ); 70 70 background-repeat: no-repeat; … … 80 80 ``` 81 81 82 Note: you will need to adjust the colo urs and sizes based on your brand.82 Note: you will need to adjust the colors and sizes based on your brand. 83 83 84 84 ### Template Tweaks … … 88 88 #### Featured Image 89 89 90 The default template does not display the featured image currently. There are many ways to add it, such as the snippet below: 91 92 ```php 93 add_action( 'pre_amp_render_post', 'xyz_amp_add_custom_actions' ); 94 function xyz_amp_add_custom_actions() { 95 add_filter( 'the_content', 'xyz_amp_add_featured_image' ); 96 } 97 98 function xyz_amp_add_featured_image( $content ) { 99 if ( has_post_thumbnail() ) { 100 // Just add the raw <img /> tag; our sanitizer will take care of it later. 101 $image = sprintf( '<p class="xyz-featured-image">%s</p>', get_the_post_thumbnail() ); 102 $content = $image . $content; 103 } 104 return $content; 90 The default template displays the featured image. If you don't want to display the featured image in your amp page, use the following code: 91 92 ```php 93 add_filter( 'amp_post_template_data', 'xyz_amp_remove_featured_image' ); 94 95 function xyz_amp_remove_featured_image( $data ) { 96 $data['featured_image'] = false; 97 return $data; 105 98 } 106 99 ``` … … 137 130 The plugin adds some default metadata to enable ["Rich Snippet" support](https://developers.google.com/structured-data/rich-snippets/articles). You can modify this using the `amp_post_template_metadata` filter. The following changes the type annotation to `NewsArticle` (from the default `BlogPosting`) and overrides the default Publisher Logo. 138 131 139 ``` 132 ``` 140 133 add_filter( 'amp_post_template_metadata', 'xyz_amp_modify_json_metadata', 10, 2 ); 141 134 … … 315 308 * You must trigger the `amp_post_template_head` action in the `<head>` section: 316 309 317 ``` 310 ``` 318 311 do_action( 'amp_post_template_head', $this ); 319 312 ``` … … 321 314 * You must trigger the `amp_post_template_footer` action right before the `</body>` tag: 322 315 323 ``` 316 ``` 324 317 do_action( 'amp_post_template_footer', $this ); 325 318 ``` … … 396 389 397 390 public function get_scripts() { 398 return array( 'amp-mustache' => 'https://cdn.ampproject.org/v0/amp-mustache-0.1.js' ); 391 return array( 392 'amp-mustache' => 'https://cdn.ampproject.org/v0/amp-mustache-0.1.js', 393 'amp-list' => 'https://cdn.ampproject.org/v0/amp-list-0.1.js', 394 ); 399 395 } 400 396 … … 491 487 ``` 492 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 493 552 ## Analytics 494 553 495 To output proper analytics tags, you can use the `amp_post_template_analytics` filter: 496 497 ``` 554 There are two options you can follow to include analytics tags in your posts. 555 556 ### Plugin Analytics Options 557 558 The plugin defines an analytics option to enable the addition of 559 [amp-analytics](https://www.ampproject.org/docs/reference/components/amp-analytics) in your posts. When the plugin is 560 active, an AMP top-level menu appears in the Dashboard with one inner sub-menu called 'Analytics': 561 562 ![AMP Options Menu](https://github.com/Automattic/amp-wp/blob/amedina/amp-analytics-customizer/readme-assets/amp-options-analytics.png) 563 564 Selecting the `Analytics` sub-menu in the AMP options menu takes us to an Analytics Options entry page, where we can 565 define the analytics tags we want to have, by specifying the vendor type (e.g. Parsely), and the associated JSON 566 configuration. 567 568 ![AMP Options Menu](https://github.com/Automattic/amp-wp/blob/amedina/amp-analytics-customizer/readme-assets/analytics-option-entries.png) 569 570 Notice that the goal of this option of the plugin is to provide a simple mechanism to insert analytics tags; 571 it provides very simple validation based solely on the validity of the JSON string provided. It is the users 572 responsibility to make sure that the values in the configuration string and the vendor type used are coherent with 573 the analytics requirements of their site . Please review the documentation in the [AMP project ](https://github.com/ampproject/amphtml/blob/master/extensions/amp-analytics/amp-analytics.md) and in [AMPByExample](https://ampbyexample.com/components/amp-analytics/). 574 575 The AMP Analytics options entry form provides a very simple validation feedback mechanism: if the JSON configuration 576 string entered is invalid (i.e. not valid JSON), an error message (in red) is displayed below the title of the 577 options window and the entry form is reloaded: 578 579 ![AMP Options Menu](https://github.com/Automattic/amp-wp/blob/amedina/amp-analytics-customizer/readme-assets/invalid-input.png) 580 581 And, if the configuration provided is actually a valid JSON string, a success message (in green) is displayed at the 582 top of the window below the title, and again the entry form is reloaded. 583 584 ![AMP Options Menu](https://github.com/Automattic/amp-wp/blob/amedina/amp-analytics-customizer/readme-assets/options-saved.png) 585 586 ### Manually 587 588 Alaternatively, you can use the `amp_post_template_analytics` filter: 589 590 ```php 498 591 add_filter( 'amp_post_template_analytics', 'xyz_amp_add_custom_analytics' ); 499 592 function xyz_amp_add_custom_analytics( $analytics ) { … … 557 650 If you want a custom template for your post type: 558 651 559 ``` 652 ``` 560 653 add_filter( 'amp_post_template_file', 'xyz_amp_set_review_template', 10, 3 ); 561 654 -
amp/trunk/readme.txt
r1673399 r1708734 2 2 Contributors: batmoo, joen, automattic, potatomaster 3 3 Tags: amp, mobile 4 Requires at least: 4. 44 Requires at least: 4. 5 5 Tested up to: 4.8 6 Stable tag: 0. 4.26 Stable tag: 0. 7 7 License: GPLv2 or later 8 8 License URI: http://www.gnu.org/licenses/gpl-2.0.html … … 14 14 This plugin adds support for the [Accelerated Mobile Pages](https://www.ampproject.org) (AMP) Project, which is an an open source initiative that aims to provide mobile optimized content that can load instantly everywhere. 15 15 16 With the plugin active, all posts on your site will have dynamically generated AMP-compatible versions, accessible by appending `/amp/` to the end your post URLs. For example, if your post URL is `http://example.com/2016/01/01/amp-on/`, you can access the AMP version at `http://example.com/2016/01/01/amp-on/amp/`. If you do not have [pretty permalinks](https://codex.wordpress.org/Using_Permalinks#mod_rewrite:_.22Pretty_Permalinks.22) enabled, you can do the same thing by appending `?amp=1`, i.e. `http://example.com/ 2016/01/01/amp-on/?amp=1`16 With the plugin active, all posts on your site will have dynamically generated AMP-compatible versions, accessible by appending `/amp/` to the end your post URLs. For example, if your post URL is `http://example.com/2016/01/01/amp-on/`, you can access the AMP version at `http://example.com/2016/01/01/amp-on/amp/`. If you do not have [pretty permalinks](https://codex.wordpress.org/Using_Permalinks#mod_rewrite:_.22Pretty_Permalinks.22) enabled, you can do the same thing by appending `?amp=1`, i.e. `http://example.com/amp=1` 17 17 18 18 Note #1: that Pages and archives are not currently supported. Pages support is being worked on. … … 32 32 = How do I customize the AMP output for my site? = 33 33 34 You can tweak a few things like colo urs from the AMP Customizer. From the Dashboard, go to `Appearance > AMP`.34 You can tweak a few things like colors from the AMP Customizer. From the Dashboard, go to `Appearance > AMP`. 35 35 36 36 For deeper level customizations, please see the readme at https://github.com/Automattic/amp-wp/blob/master/readme.md … … 54 54 == Changelog == 55 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 56 72 = 0.4.2 (2016-10-13) = 57 73 … … 73 89 - New template: spiffy, shiny, and has the fresh theme smell (props allancole and the Automattic Theme Team). 74 90 - *Warning*: The template update has potential breaking changes. Please see https://wordpress.org/support/topic/v0-4-whats-new-and-possible-breaking-changes/ 75 - AMP Customizer: Pick your colo urs and make the template your own (props DrewAPicture and 10up)91 - AMP Customizer: Pick your colors and make the template your own (props DrewAPicture and 10up) 76 92 - Fix: support for inline styles (props coreymckrill). 77 93 - Fix: no more fatal errors when tags not supported by post type (props david-binda) -
amp/trunk/templates/footer.php
r1510272 r1708734 3 3 <h2><?php echo esc_html( $this->get( 'blog_name' ) ); ?></h2> 4 4 <p> 5 <a href="<?php echo esc_url( __( 'https://wordpress.org/', 'amp' ) ); ?>"><?php printf( __( 'Powered by %s', 'amp' ), 'WordPress'); ?></a>5 <a href="<?php echo esc_url( ); ?></a> 6 6 </p> 7 <a href="#top" class="back-to-top"><?php _e( 'Back to top', 'amp' ); ?></a>7 <a href="#top" class="back-to-top"><?php _e( 'Back to top', 'amp' ); ?></a> 8 8 </div> 9 9 </footer> -
amp/trunk/templates/header-bar.php
r1510272 r1708734 3 3 <a href="<?php echo esc_url( $this->get( 'home_url' ) ); ?>"> 4 4 <?php $site_icon_url = $this->get( 'site_icon_url' ); 5 5 if ( $site_icon_url ) : ?> 6 6 <amp-img src="<?php echo esc_url( $site_icon_url ); ?>" width="32" height="32" class="amp-wp-site-icon"></amp-img> 7 7 <?php endif; ?> -
amp/trunk/templates/meta-author.php
r1510272 r1708734 1 1 <?php $post_author = $this->get( 'post_author' ); ?> 2 2 <?php if ( $post_author ) : ?> 3 <?php $author_avatar_url = get_avatar_url( $post_author->user_email, array( 'size' => 24 ) ); ?>4 3 <div class="amp-wp-meta amp-wp-byline"> 5 4 <?php if ( function_exists( 'get_avatar_url' ) ) : ?> 6 <amp-img src="<?php echo esc_url( $author_avatar_url); ?>" width="24" height="24" layout="fixed"></amp-img>5 <amp-img src="<?php echo esc_url( ); ?>" width="24" height="24" layout="fixed"></amp-img> 7 6 <?php endif; ?> 8 7 <span class="amp-wp-author author vcard"><?php echo esc_html( $post_author->display_name ); ?></span> -
amp/trunk/templates/style.php
r1510272 r1708734 135 135 /** site icon is 32px **/ 136 136 background-color: <?php echo sanitize_hex_color( $header_color ); ?>; 137 border: 1px solid <?php echo sanitize_hex_color( 137 border: 1px solid <?php echo sanitize_hex_color( $header_color ); ?>; 138 138 border-radius: 50%; 139 139 position: absolute;
Note: See TracChangeset
for help on using the changeset viewer.