Plugin Directory

Changeset 1708734

Timestamp:
08/05/2017 03:59:01 AM (7 years ago)
Author:
batmoo
Message:

Update to 0.5

https://github.com/Automattic/amp-wp/releases/tag/0.5

Location:
amp/trunk
Files:
34 added
1 deleted
31 edited

Legend:

Unmodified
Added
Removed
  • amp/trunk/amp.php

    r1514204 r1708734  
    66 * Author: Automattic
    77 * Author URI: https://automattic.com
    8  * Version: 0.4.2
     8 * Version: 0.
    99 * Text Domain: amp
    1010 * Domain Path: /languages/
     
    1414define( 'AMP__FILE__', __FILE__ );
    1515define( 'AMP__DIR__', dirname( __FILE__ ) );
    16 define( 'AMP__VERSION', '0.4.2' );
     16define( 'AMP__VERSION', '0.' );
    1717
    1818require_once( AMP__DIR__ . '/back-compat/back-compat.php' );
     
    6161    add_filter( 'request', 'amp_force_query_var_value' );
    6262    add_action( 'wp', 'amp_maybe_add_actions' );
     63
     64
     65
    6366
    6467    if ( class_exists( 'Jetpack' ) && ! ( defined( 'IS_WPCOM' ) && IS_WPCOM ) ) {
     
    115118    require_once( AMP__DIR__ . '/includes/amp-post-template-actions.php' );
    116119    require_once( AMP__DIR__ . '/includes/amp-post-template-functions.php' );
     120
    117121}
    118122
     
    122126
    123127function amp_render() {
     128
     129
     130
     131
     132
     133
     134
     135
     136
     137
     138
    124139    amp_load_classes();
    125140
    126     $post_id = get_queried_object_id();
    127141    do_action( 'pre_amp_render_post', $post_id );
    128142
     
    130144    $template = new AMP_Post_Template( $post_id );
    131145    $template->load();
    132     exit;
    133146}
    134147
     
    158171}
    159172add_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  
    4747        // Our custom panels only need to go for AMP Customizer requests though
    4848        if ( self::is_amp_customizer() ) {
    49             if ( empty( $_GET['url'] ) ) {
     49            if ( empty( $_GET['url'] ) ) {
    5050                $wp_customize->set_preview_url( amp_admin_get_preview_permalink() );
    5151            }
     
    157157
    158158    public function force_mobile_preview( $devices ) {
    159         if ( isset( $devices[ 'mobile' ] ) ) {
     159        if ( isset( $devices[] ) ) {
    160160            $devices['mobile']['default'] = true;
    161161            unset( $devices['desktop']['default'] );
     
    166166
    167167    public static function is_amp_customizer() {
    168         return ! empty( $_REQUEST[ AMP_CUSTOMIZER_QUERY_VAR ] );
     168        return ! empty( $_REQUEST[ AMP_CUSTOMIZER_QUERY_VAR ] );
    169169    }
    170170}
  • amp/trunk/includes/admin/functions.php

    r1510272 r1708734  
    11<?php
    22// Callbacks for adding AMP-related things to the admin.
     3
     4
     5
    36
    47define( 'AMP_CUSTOMIZER_QUERY_VAR', 'customize_amp' );
     
    2326}
    2427
    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_slug
    42     );
    43 }
    44 
    4528function amp_admin_get_preview_permalink() {
    4629    /**
    47      * Filter the post type to retrieve the latest of for use in the AMP template customizer.
     30     * Filter the post type to retrieve the latest for use in the AMP template customizer.
    4831     *
    4932     * @param string $post_type Post type slug. Default 'post'.
     
    7053    return amp_get_permalink( $post_id );
    7154}
     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  
    88    }
    99
    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 {
    1114        $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 ) );
    1415    }
    1516
     
    4041 */
    4142function is_amp_endpoint() {
     43
     44
     45
     46
    4247    return false !== get_query_var( AMP_QUERY_VAR, false );
    4348}
  • amp/trunk/includes/amp-post-template-actions.php

    r1510272 r1708734  
    22// Callbacks for adding content to an AMP template
    33
    4 add_action( 'amp_post_template_head', 'amp_post_template_add_title' );
     4function 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
    516function amp_post_template_add_title( $amp_template ) {
    617    ?>
     
    920}
    1021
    11 add_action( 'amp_post_template_head', 'amp_post_template_add_canonical' );
    1222function amp_post_template_add_canonical( $amp_template ) {
    1323    ?>
     
    1626}
    1727
    18 add_action( 'amp_post_template_head', 'amp_post_template_add_scripts' );
    1928function amp_post_template_add_scripts( $amp_template ) {
    2029    $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>
    2333    <?php endforeach; ?>
    2434    <script src="<?php echo esc_url( $amp_template->get( 'amp_runtime_script' ) ); ?>" async></script>
     
    2636}
    2737
    28 add_action( 'amp_post_template_head', 'amp_post_template_add_fonts' );
    2938function amp_post_template_add_fonts( $amp_template ) {
    3039    $font_urls = $amp_template->get( 'font_urls', array() );
    31     foreach( $font_urls as $slug => $url ) : ?>
     40    foreach( $font_urls as $slug => $url ) : ?>
    3241        <link rel="stylesheet" href="<?php echo esc_url( $url ); ?>">
    3342    <?php endforeach;
    3443}
    3544
    36 add_action( 'amp_post_template_head', 'amp_post_template_add_boilerplate_css' );
    3745function amp_post_template_add_boilerplate_css( $amp_template ) {
    3846    ?>
     
    4149}
    4250
    43 add_action( 'amp_post_template_head', 'amp_post_template_add_schemaorg_metadata' );
    4451function amp_post_template_add_schemaorg_metadata( $amp_template ) {
    4552    $metadata = $amp_template->get( 'metadata' );
     
    4855    }
    4956    ?>
    50     <script type="application/ld+json"><?php echo json_encode( $metadata ); ?></script>
     57    <script type="application/ld+json"><?php echo json_encode( $metadata ); ?></script>
    5158    <?php
    5259}
    5360
    54 add_action( 'amp_post_template_css', 'amp_post_template_add_styles', 99 );
    5561function amp_post_template_add_styles( $amp_template ) {
    5662    $styles = $amp_template->get( 'post_amp_styles' );
     
    5864        echo '/* Inline styles */' . PHP_EOL;
    5965        foreach ( $styles as $selector => $declarations ) {
    60             $declarations = implode( ";", $declarations ) . ";";
     66            $declarations = implode( ;
    6167            printf( '%1$s{%2$s}', $selector, $declarations );
    6268        }
     
    6470}
    6571
    66 add_action( 'amp_post_template_data', 'amp_post_template_add_analytics_script' );
    6772function amp_post_template_add_analytics_script( $data ) {
    6873    if ( ! empty( $data['amp_analytics'] ) ) {
     
    7277}
    7378
    74 add_action( 'amp_post_template_footer', 'amp_post_template_add_analytics_data' );
    7579function amp_post_template_add_analytics_data( $amp_template ) {
    7680    $analytics_entries = $amp_template->get( 'amp_analytics' );
     
    8185    foreach ( $analytics_entries as $id => $analytics_entry ) {
    8286        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' );
    8488            continue;
    8589        }
    86 
    8790        $script_element = AMP_HTML_Utils::build_tag( 'script', array(
    8891            'type' => 'application/json',
    89         ), json_encode( $analytics_entry['config_data'] ) );
     92        ), json_encode( $analytics_entry['config_data'] ) );
    9093
    9194        $amp_analytics_attr = array_merge( array(
  • amp/trunk/includes/amp-post-template-functions.php

    r1514204 r1708734  
    99
    1010        // 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 ) ) {
    1212            return $color;
    1313        }
  • amp/trunk/includes/class-amp-content.php

    r1514204 r1708734  
    6464
    6565            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' );
    6767                continue;
    6868            }
     
    100100        foreach ( $sanitizer_classes as $sanitizer_class => $args ) {
    101101            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' );
    103103                continue;
    104104            }
     
    107107
    108108            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' );
    110110                continue;
    111111            }
  • amp/trunk/includes/class-amp-post-template.php

    r1514204 r1708734  
    44require_once( AMP__DIR__ . '/includes/utils/class-amp-html-utils.php' );
    55require_once( AMP__DIR__ . '/includes/utils/class-amp-string-utils.php' );
     6
    67
    78require_once( AMP__DIR__ . '/includes/class-amp-content.php' );
     
    910require_once( AMP__DIR__ . '/includes/sanitizers/class-amp-style-sanitizer.php' );
    1011require_once( AMP__DIR__ . '/includes/sanitizers/class-amp-blacklist-sanitizer.php' );
     12
    1113require_once( AMP__DIR__ . '/includes/sanitizers/class-amp-img-sanitizer.php' );
    1214require_once( AMP__DIR__ . '/includes/sanitizers/class-amp-video-sanitizer.php' );
    1315require_once( AMP__DIR__ . '/includes/sanitizers/class-amp-iframe-sanitizer.php' );
    1416require_once( AMP__DIR__ . '/includes/sanitizers/class-amp-audio-sanitizer.php' );
     17
    1518
    1619require_once( AMP__DIR__ . '/includes/embeds/class-amp-twitter-embed.php' );
    1720require_once( AMP__DIR__ . '/includes/embeds/class-amp-youtube-embed.php' );
     21
     22
     23
    1824require_once( AMP__DIR__ . '/includes/embeds/class-amp-gallery-embed.php' );
    1925require_once( AMP__DIR__ . '/includes/embeds/class-amp-instagram-embed.php' );
    2026require_once( AMP__DIR__ . '/includes/embeds/class-amp-vine-embed.php' );
    2127require_once( AMP__DIR__ . '/includes/embeds/class-amp-facebook-embed.php' );
     28
    2229
    2330class AMP_Post_Template {
     
    7077                'merriweather' => 'https://fonts.googleapis.com/css?family=Merriweather:400,400italic,700,700italic',
    7178            ),
     79
     80
    7281
    7382            /**
     
    8291             */
    8392            'amp_analytics' => apply_filters( 'amp_post_template_analytics', array(), $this->post ),
    84         );
     93        );
    8594
    8695        $this->build_post_content();
     
    96105            return $this->data[ $property ];
    97106        } 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' );
    99108        }
    100109
     
    224233                'AMP_Twitter_Embed_Handler' => array(),
    225234                'AMP_YouTube_Embed_Handler' => array(),
     235
     236
     237
    226238                'AMP_Instagram_Embed_Handler' => array(),
    227239                'AMP_Vine_Embed_Handler' => array(),
    228240                'AMP_Facebook_Embed_Handler' => array(),
     241
    229242                'AMP_Gallery_Embed_Handler' => array(),
    230243            ), $this->post ),
    231244            apply_filters( 'amp_content_sanitizers', array(
    232245                 'AMP_Style_Sanitizer' => array(),
    233                  'AMP_Blacklist_Sanitizer' => array(),
     246                 'AMP_Blacklist_Sanitizer' => array(),
    234247                 'AMP_Img_Sanitizer' => array(),
    235248                 'AMP_Video_Sanitizer' => array(),
    236249                 'AMP_Audio_Sanitizer' => array(),
     250
    237251                 'AMP_Iframe_Sanitizer' => array(
    238252                     'add_placeholder' => true,
    239253                 ),
     254
    240255            ), $this->post ),
    241256            array(
     
    246261        $this->add_data_by_key( 'post_amp_content', $amp_content->get_amp_content() );
    247262        $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() );
    249264    }
    250265
     
    275290            array( 'AMP_Img_Sanitizer' => array() ),
    276291            array(
    277                 'content_max_width' => $this->get( 'content_max_width' )
     292                'content_max_width' => $this->get( 'content_max_width' )
    278293            )
    279294        );
     
    289304
    290305        if ( $featured_styles ) {
    291             $this->add_data_by_key( 'post_amp_styles', $featured_styles );
     306            $this->_key( 'post_amp_styles', $featured_styles );
    292307        }
    293308    }
     
    382397        $file = apply_filters( 'amp_post_template_file', $file, $template_type, $this->post );
    383398        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' );
    385400            return;
    386401        }
  • amp/trunk/includes/embeds/class-amp-gallery-embed.php

    r1364370 r1708734  
    4040            'include'    => '',
    4141            'exclude'    => '',
    42             'size'       => array( $this->args['width'], $this->args['height'] )
     42            'size'       => array( $this->args['width'], $this->args['height'] )
    4343        ), $attr, 'gallery' );
    4444
  • amp/trunk/includes/embeds/class-amp-instagram-embed.php

    r1478266 r1708734  
    5353
    5454    public function oembed( $matches, $attr, $url, $rawattr ) {
    55         return $this->render( array( 'url' => $url, 'instagram_id' =>  end( $matches ) ) );
     55        return $this->render( array( 'url' => $url, 'instagram_id' => end( $matches ) ) );
    5656    }
    5757
  • amp/trunk/includes/embeds/class-amp-vine-embed.php

    r1337793 r1708734  
    2929
    3030    public function oembed( $matches, $attr, $url, $rawattr ) {
    31         return $this->render( array( 'url' => $url, 'vine_id' =>  end( $matches ) ) );
     31        return $this->render( array( 'url' => $url, 'vine_id' => end( $matches ) ) );
    3232    }
    3333
  • amp/trunk/includes/embeds/class-amp-youtube-embed.php

    r1510272 r1708734  
    4949        if ( isset( $attr[0] ) ) {
    5050            $url = ltrim( $attr[0] , '=' );
    51         } elseif ( function_exists ( 'shortcode_new_to_old_params' ) ) {
     51        } elseif ( function_exists( 'shortcode_new_to_old_params' ) ) {
    5252            $url = shortcode_new_to_old_params( $attr );
    5353        }
     
    9393    private function get_video_id_from_url( $url ) {
    9494        $video_id = false;
    95         $parsed_url = parse_url( $url );
     95        $parsed_url = parse_url( $url );
    9696
    9797        if ( self::SHORT_URL_HOST === substr( $parsed_url['host'], -strlen( self::SHORT_URL_HOST ) ) ) {
     
    114114            $parts = explode( '/', $parsed_url['path'] );
    115115
    116             if ( in_array( $parts[1], array( 'v', 'e', 'embed' ) ) ) {
     116            if ( in_array( $parts[1], array( 'v', 'e', 'embed' ) ) ) {
    117117                $video_id = $parts[2];
    118118            }
  • amp/trunk/includes/sanitizers/class-amp-base-sanitizer.php

    r1510272 r1708734  
    4343
    4444        if ( AMP_String_Utils::endswith( $value, '%' ) ) {
    45             if ( 'width' === $dimension && isset( $this->args[ 'content_max_width'] ) ) {
     45            if ( 'width' === $dimension && isset( $this->args['content_max_width'] ) ) {
    4646                $percentage = absint( $value ) / 100;
    47                 return round( $percentage * $this->args[ 'content_max_width'] );
     47                return round( $percentage * $this->args['content_max_width'] );
    4848            }
    4949        }
  • amp/trunk/includes/sanitizers/class-amp-blacklist-sanitizer.php

    r1510272 r1708734  
    88 * See following for blacklist:
    99 *     https://github.com/ampproject/amphtml/blob/master/spec/amp-html-format.md#html-tags
     10
     11
     12
    1013 */
    1114class AMP_Blacklist_Sanitizer extends AMP_Base_Sanitizer {
     
    2932
    3033    private function strip_attributes_recursive( $node, $bad_attributes, $bad_protocols ) {
    31         if ( $node->nodeType !== XML_ELEMENT_NODE ) {
     34        if ( ) {
    3235            return;
    3336        }
     
    3740        // Some nodes may contain valid content but are themselves invalid.
    3841        // Remove the node but preserve the children.
    39         if ( 'font' === $node_name ) {
     42        if ( 'font' === $node_name ) {
    4043            $this->replace_node_with_children( $node, $bad_attributes, $bad_protocols );
    4144            return;
     
    5053                $attribute = $node->attributes->item( $i );
    5154                $attribute_name = strtolower( $attribute->name );
    52                 if ( in_array( $attribute_name, $bad_attributes ) ) {
     55                if ( in_array( $attribute_name, $bad_attributes ) ) {
    5356                    $node->removeAttribute( $attribute_name );
    5457                    continue;
     
    5659
    5760                // 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' ) && ) {
    5962                    $node->removeAttribute( $attribute_name );
    6063                    continue;
     
    125128        $href = $node->getAttribute( 'href' );
    126129
    127         // If no href is set and this isn't an anchor, it's invalid
    128130        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' );
    136134        }
    137135
     
    151149
    152150        if ( false === filter_var( $href, FILTER_VALIDATE_URL )
    153             && ! in_array( $protocol, $special_protocols ) ) {
     151            && ! in_array( $protocol, $special_protocols ) ) {
    154152            return false;
    155153        }
    156154
    157         if ( ! in_array( $protocol, $valid_protocols ) ) {
     155        if ( ! in_array( $protocol, $valid_protocols ) ) {
    158156            return false;
    159157        }
  • amp/trunk/includes/sanitizers/class-amp-iframe-sanitizer.php

    r1478266 r1708734  
    9898                    break;
    9999
    100 
    101100                case 'frameborder':
    102101                    if ( '0' !== $value && '1' !== $value ) {
     
    118117        }
    119118
    120         if ( ! isset( $out[ 'sandbox' ] ) ) {
    121             $out[ 'sandbox' ] = self::SANDBOX_DEFAULTS;
     119        if ( ! isset( $out[] ) ) {
     120            $out[] = self::SANDBOX_DEFAULTS;
    122121        }
    123122
  • amp/trunk/includes/sanitizers/class-amp-img-sanitizer.php

    r1510272 r1708734  
    1919
    2020    public function sanitize() {
     21
    2122        $nodes = $this->dom->getElementsByTagName( self::$tag );
     23
     24
    2225        $num_nodes = $nodes->length;
     26
    2327        if ( 0 === $num_nodes ) {
    2428            return;
     
    2731        for ( $i = $num_nodes - 1; $i >= 0; $i-- ) {
    2832            $node = $nodes->item( $i );
    29             $old_attributes = AMP_DOM_Utils::get_node_attributes_as_assoc_array( $node );
    3033
    31             if ( empty( $old_attributes['src'] ) ) {
     34            if ( ) ) {
    3235                $node->parentNode->removeChild( $node );
    3336                continue;
    3437            }
    3538
    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        }
    3746
    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'] );
    4473                }
    4574            }
     75
     76
    4677
    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    }
    5196
    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 );
    53106            }
    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 );
    66107        }
    67108    }
     
    104145    private function is_gif_url( $url ) {
    105146        $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 ;
    108149    }
    109150}
  • amp/trunk/includes/sanitizers/class-amp-style-sanitizer.php

    r1512429 r1708734  
    1919
    2020    private function collect_styles_recursive( $node ) {
    21         if ( $node->nodeType !== XML_ELEMENT_NODE ) {
     21        if ( ) {
    2222            return;
    2323        }
     
    5757        }
    5858
    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
    6164        sort( $styles );
    6265
  • amp/trunk/includes/sanitizers/class-amp-video-sanitizer.php

    r1478266 r1708734  
    1010
    1111    public static $tag = 'video';
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
    1223
    1324    public function sanitize() {
     
    5162                $node->parentNode->replaceChild( $new_node, $node );
    5263            }
     64
     65
    5366        }
    5467    }
  • amp/trunk/includes/settings/class-amp-customizer-design-settings.php

    r1510272 r1708734  
    2424            'default'           => self::DEFAULT_HEADER_COLOR,
    2525            'sanitize_callback' => 'sanitize_hex_color',
    26             'transport'         => 'postMessage'
     26            'transport'         => 'postMessage'
    2727        ) );
    2828
     
    3232            'default'           => self::DEFAULT_HEADER_BACKGROUND_COLOR,
    3333            'sanitize_callback' => 'sanitize_hex_color',
    34             'transport'         => 'postMessage'
     34            'transport'         => 'postMessage'
    3535        ) );
    3636
     
    4040            'default'           => self::DEFAULT_COLOR_SCHEME,
    4141            'sanitize_callback' => array( __CLASS__ , 'sanitize_color_scheme' ),
    42             'transport'         => 'postMessage'
     42            'transport'         => 'postMessage'
    4343        ) );
    4444    }
    4545
    46     public function register_customizer_ui( $wp_customize ) {
     46    public function register_customizer_ui( $wp_customize ) {
    4747        $wp_customize->add_section( 'amp_design', array(
    4848            'title' => __( 'Design', 'amp' ),
     
    5656                'label'    => __( 'Header Text Color', 'amp' ),
    5757                'section'  => 'amp_design',
    58                 'priority' => 10
     58                'priority' => 10
    5959            ) )
    6060        );
     
    6666                'label'    => __( 'Header Background & Link Color', 'amp' ),
    6767                'section'  => 'amp_design',
    68                 'priority' => 20
     68                'priority' => 20
    6969            ) )
    7070        );
     
    110110    protected static function get_color_scheme_names() {
    111111        return array(
    112             'light'   => __( 'Light', 'amp'),
     112            'light'   => __( 'Light', 'amp'),
    113113            'dark'    => __( 'Dark', 'amp' ),
    114114        );
     
    130130                'muted_text_color' => '#b1b1b1',
    131131                'border_color'     => '#707070',
    132             )
     132            )
    133133        );
    134134    }
     
    148148        $scheme_slugs = array_keys( $schemes );
    149149
    150         if ( ! in_array( $value, $scheme_slugs ) ) {
     150        if ( ! in_array( $value, $scheme_slugs ) ) {
    151151            $value = self::DEFAULT_COLOR_SCHEME;
    152152        }
  • amp/trunk/includes/utils/class-amp-dom-utils.php

    r1514204 r1708734  
    9696            // Not all are valid AMP, but we include them for completeness.
    9797            $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',
    99116            );
    100117        }
    101118
    102         return in_array( $tag, $self_closing_tags );
     119        return in_array( $tag, $self_closing_tags );
    103120    }
    104121}
  • amp/trunk/includes/utils/class-amp-html-utils.php

    r1337793 r1708734  
    1818        return implode( ' ', $string );
    1919    }
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
    2032}
  • amp/trunk/includes/utils/class-amp-image-dimension-extractor.php

    r1357059 r1708734  
    33class AMP_Image_Dimension_Extractor {
    44    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 ) {
    79        if ( ! self::$callbacks_registered ) {
    810            self::register_callbacks();
    911        }
    1012
    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;
    1725    }
    1826
     
    3038        }
    3139
    32         $parsed = parse_url( $url );
     40        $parsed = parse_url( $url );
    3341        if ( ! isset( $parsed['host'] ) ) {
    3442            $path = '';
     
    4856        self::$callbacks_registered = true;
    4957
    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 ) {
    101161        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();
    118238    }
    119239}
  • amp/trunk/includes/utils/class-amp-string-utils.php

    r1478266 r1708734  
    55        return '' !== $haystack
    66            && '' !== $needle
    7             && $needle === substr( $haystack, -strlen( $needle ) );
     7            && ;
    88    }
    99}
  • amp/trunk/jetpack-helper.php

    r1364370 r1708734  
    5757        $tz = get_option( 'gmt_offset' );
    5858        $v = 'ext';
    59         $blog_url = parse_url( site_url() );
     59        $blog_url = parse_url( site_url() );
    6060        $srv = $blog_url['host'];
    6161        $j = sprintf( '%s:%s', JETPACK__API_VERSION, JETPACK__VERSION );
     
    6464    }
    6565
    66     $data['host'] = rawurlencode( $_SERVER['HTTP_HOST'] );
     66    $data['host'] =
    6767    $data['rand'] = 'RANDOM'; // amp placeholder
    6868    $data['ref'] = 'DOCUMENT_REFERRER'; // amp placeholder
  • amp/trunk/readme.md

    r1514204 r1708734  
    55This 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.
    66
    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`
     7With 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`
    88
    99Note #1: that Pages and archives are not currently supported.
     
    5454#### Logo Only
    5555
    56 If you want to hide the site text and just show a logo, use the `amp_post_template_css` action. The following colours the title bar black, hides the site title, and replaces it with a centered logo:
    57 
    58 ```
     56If 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```
    5959add_action( 'amp_post_template_css', 'xyz_amp_additional_css_styles' );
    6060
     
    6262    // only CSS here please...
    6363    ?>
    64     nav.amp-wp-title-bar {
     64    r {
    6565        padding: 12px 0;
    6666        background: #000;
    6767    }
    68     nav.amp-wp-title-bar a {
     68    r a {
    6969        background-image: url( 'https://example.com/path/to/logo.png' );
    7070        background-repeat: no-repeat;
     
    8080```
    8181
    82 Note: you will need to adjust the colours and sizes based on your brand.
     82Note: you will need to adjust the colors and sizes based on your brand.
    8383
    8484### Template Tweaks
     
    8888#### Featured Image
    8989
    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;
     90The 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
     93add_filter( 'amp_post_template_data', 'xyz_amp_remove_featured_image' );
     94
     95function xyz_amp_remove_featured_image( $data ) {
     96    $data['featured_image'] = false;
     97    return $data;
    10598}
    10699```
     
    137130The 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.
    138131
    139 ```
     132```
    140133add_filter( 'amp_post_template_metadata', 'xyz_amp_modify_json_metadata', 10, 2 );
    141134
     
    315308* You must trigger the `amp_post_template_head` action in the `<head>` section:
    316309
    317 ```
     310```
    318311do_action( 'amp_post_template_head', $this );
    319312```
     
    321314* You must trigger the `amp_post_template_footer` action right before the `</body>` tag:
    322315
    323 ```
     316```
    324317do_action( 'amp_post_template_footer', $this );
    325318```
     
    396389
    397390    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        );
    399395    }
    400396
     
    491487```
    492488
     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
    493552## Analytics
    494553
    495 To output proper analytics tags, you can use the `amp_post_template_analytics` filter:
    496 
    497 ```
     554There are two options you can follow to include analytics tags in your posts.
     555
     556### Plugin Analytics Options
     557
     558The 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
     570Notice 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   
     581And, if the configuration provided is actually a valid JSON string, a success message (in green) is displayed at the
     582top 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
     588Alaternatively, you can use the `amp_post_template_analytics` filter:
     589
     590```php
    498591add_filter( 'amp_post_template_analytics', 'xyz_amp_add_custom_analytics' );
    499592function xyz_amp_add_custom_analytics( $analytics ) {
     
    557650If you want a custom template for your post type:
    558651
    559 ```
     652```
    560653add_filter( 'amp_post_template_file', 'xyz_amp_set_review_template', 10, 3 );
    561654
  • amp/trunk/readme.txt

    r1673399 r1708734  
    22Contributors: batmoo, joen, automattic, potatomaster
    33Tags: amp, mobile
    4 Requires at least: 4.4
     4Requires at least: 4.
    55Tested up to: 4.8
    6 Stable tag: 0.4.2
     6Stable tag: 0.
    77License: GPLv2 or later
    88License URI: http://www.gnu.org/licenses/gpl-2.0.html
     
    1414This 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.
    1515
    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`
     16With 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`
    1717
    1818Note #1: that Pages and archives are not currently supported. Pages support is being worked on.
     
    3232= How do I customize the AMP output for my site? =
    3333
    34 You can tweak a few things like colours from the AMP Customizer. From the Dashboard, go to `Appearance > AMP`.
     34You can tweak a few things like colors from the AMP Customizer. From the Dashboard, go to `Appearance > AMP`.
    3535
    3636For deeper level customizations, please see the readme at https://github.com/Automattic/amp-wp/blob/master/readme.md
     
    5454== Changelog ==
    5555
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
    5672= 0.4.2 (2016-10-13) =
    5773
     
    7389- New template: spiffy, shiny, and has the fresh theme smell (props allancole and the Automattic Theme Team).
    7490- *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 colours 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)
    7692- Fix: support for inline styles (props coreymckrill).
    7793- Fix: no more fatal errors when tags not supported by post type (props david-binda)
  • amp/trunk/templates/footer.php

    r1510272 r1708734  
    33        <h2><?php echo esc_html( $this->get( 'blog_name' ) ); ?></h2>
    44        <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>
    66        </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>
    88    </div>
    99</footer>
  • amp/trunk/templates/header-bar.php

    r1510272 r1708734  
    33        <a href="<?php echo esc_url( $this->get( 'home_url' ) ); ?>">
    44            <?php $site_icon_url = $this->get( 'site_icon_url' );
    5                 if ( $site_icon_url ) : ?>
     5            if ( $site_icon_url ) : ?>
    66                <amp-img src="<?php echo esc_url( $site_icon_url ); ?>" width="32" height="32" class="amp-wp-site-icon"></amp-img>
    77            <?php endif; ?>
  • amp/trunk/templates/meta-author.php

    r1510272 r1708734  
    11<?php $post_author = $this->get( 'post_author' ); ?>
    22<?php if ( $post_author ) : ?>
    3     <?php $author_avatar_url = get_avatar_url( $post_author->user_email, array( 'size' => 24 ) ); ?>
    43    <div class="amp-wp-meta amp-wp-byline">
    54        <?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>
    76        <?php endif; ?>
    87        <span class="amp-wp-author author vcard"><?php echo esc_html( $post_author->display_name ); ?></span>
  • amp/trunk/templates/style.php

    r1510272 r1708734  
    135135    /** site icon is 32px **/
    136136    background-color: <?php echo sanitize_hex_color( $header_color ); ?>;
    137     border: 1px solid <?php echo sanitize_hex_color(  $header_color ); ?>;
     137    border: 1px solid <?php echo sanitize_hex_color( $header_color ); ?>;
    138138    border-radius: 50%;
    139139    position: absolute;
Note: See TracChangeset for help on using the changeset viewer.