Skip to content

Commit c4c4274

Browse files
committed
Introduce ampdevmode data flag on script/style dependencies to indicate data-ampdevmode needed
1 parent ebead4f commit c4c4274

File tree

4 files changed

+101
-44
lines changed

4 files changed

+101
-44
lines changed

includes/amp-helper-functions.php

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -959,8 +959,28 @@ function amp_get_content_sanitizers( $post = null ) {
959959
if ( is_admin_bar_showing() ) {
960960
$dev_mode_xpaths[] = '//*[ @id = "wpadminbar" ]';
961961
$dev_mode_xpaths[] = '//*[ @id = "wpadminbar" ]//*';
962-
$dev_mode_xpaths[] = '//style[ @id = "admin-bar-inline-css" ]';
963962
}
963+
964+
// Ensure script localization data gets flagged for dev mode. This only applies to wp_localize_script() as
965+
// inline scripts added via wp_add_inline_script() get filtered by script_loader_tag and thus will have the
966+
// data-ampdevmode attribute added via AMP_Theme_Support::filter_script_loader_tag_for_dev_mode().
967+
foreach ( wp_scripts()->done as $script_handle ) { // @todo Fail! This is currently being called _before_ the template is rendered, so it will always be empty.
968+
if ( ! AMP_Theme_Support::dependency_needs_dev_mode( wp_scripts(), $script_handle ) ) {
969+
continue;
970+
}
971+
$data = wp_scripts()->get_data( $script_handle, 'data' );
972+
if ( preg_match( '/(\bvar\s*\w+\s+=)/', $data, $matches ) ) {
973+
$dev_mode_xpaths[] = sprintf( '//script[ not( @src ) ][ contains( text(), "%s" ) ]', $matches[1] );
974+
}
975+
}
976+
977+
// Ensure all inline styles added via wp_add_inline_style() get the data-ampdevmode attribute.
978+
foreach ( wp_styles()->done as $style_handle ) { // @todo Fail! This is currently being called _before_ the template is rendered, so it will always be empty.
979+
if ( AMP_Theme_Support::dependency_needs_dev_mode( wp_styles(), $style_handle ) ) {
980+
$dev_mode_xpaths[] = sprintf( '//style[ @id = "%s" ]', "$style_handle-inline-css" );
981+
}
982+
}
983+
964984
$sanitizers = array_merge(
965985
[
966986
'AMP_Dev_Mode_Sanitizer' => [

includes/class-amp-theme-support.php

Lines changed: 41 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1098,6 +1098,8 @@ static function( $html ) {
10981098
);
10991099

11001100
add_action( 'admin_bar_init', [ __CLASS__, 'init_admin_bar' ] );
1101+
add_filter( 'style_loader_tag', [ __CLASS__, 'filter_style_loader_tag_for_dev_mode' ], 10, 2 );
1102+
add_filter( 'script_loader_tag', [ __CLASS__, 'filter_script_loader_tag_for_dev_mode' ], 10, 2 );
11011103
add_action( 'wp_head', 'amp_add_generator_metadata', 20 );
11021104
add_action( 'wp_enqueue_scripts', [ __CLASS__, 'enqueue_assets' ], 0 ); // Enqueue before theme's styles.
11031105
add_action( 'wp_enqueue_scripts', [ __CLASS__, 'dequeue_customize_preview_scripts' ], 1000 );
@@ -1427,8 +1429,6 @@ public static function filter_cancel_comment_reply_link( $formatted_link, $link,
14271429
* @since 1.0
14281430
*/
14291431
public static function init_admin_bar() {
1430-
add_filter( 'style_loader_tag', [ __CLASS__, 'filter_admin_bar_style_loader_tag' ], 10, 2 );
1431-
add_filter( 'script_loader_tag', [ __CLASS__, 'filter_admin_bar_script_loader_tag' ], 10, 2 );
14321432

14331433
// Inject the data-ampdevmode attribute into the admin bar bump style. See \WP_Admin_Bar::initialize().
14341434
if ( current_theme_supports( 'admin-bar' ) ) {
@@ -1551,40 +1551,53 @@ protected static function is_exclusively_dependent( WP_Dependencies $dependencie
15511551
}
15521552

15531553
/**
1554-
* Add data-ampdevmode attribute to any enqueued style that depends on the admin-bar.
1554+
* Determine whether a given dependency handle needs dev mode.
15551555
*
1556-
* @since 1.3
1556+
* @since 1.5
1557+
*
1558+
* @param WP_Dependencies $dependencies Dependencies (wither WP_Scripts or WP_Styles).
1559+
* @param string $handle Dependency handle (for script or style).
1560+
* @return bool Whether the <script>, <link>, or <style> needs dev mode.
1561+
*/
1562+
public static function dependency_needs_dev_mode( WP_Dependencies $dependencies, $handle ) {
1563+
return (
1564+
$dependencies->get_data( $handle, 'ampdevmode' )
1565+
||
1566+
(
1567+
in_array( $handle, $dependencies->registered['admin-bar']->deps, true ) ?
1568+
self::is_exclusively_dependent( $dependencies, $handle, 'admin-bar' ) :
1569+
self::has_dependency( $dependencies, $handle, 'admin-bar' )
1570+
)
1571+
);
1572+
}
1573+
1574+
/**
1575+
* Add data-ampdevmode attribute to any enqueued style that is flagged for dev mode or which depends on the admin-bar.
1576+
*
1577+
* @since 1.5
15571578
*
15581579
* @param string $tag The link tag for the enqueued style.
15591580
* @param string $handle The style's registered handle.
15601581
* @return string Tag.
15611582
*/
1562-
public static function filter_admin_bar_style_loader_tag( $tag, $handle ) {
1563-
if (
1564-
in_array( $handle, wp_styles()->registered['admin-bar']->deps, true ) ?
1565-
self::is_exclusively_dependent( wp_styles(), $handle, 'admin-bar' ) :
1566-
self::has_dependency( wp_styles(), $handle, 'admin-bar' )
1567-
) {
1583+
public static function filter_style_loader_tag_for_dev_mode( $tag, $handle ) {
1584+
if ( self::dependency_needs_dev_mode( wp_styles(), $handle ) ) {
15681585
$tag = preg_replace( '/(?<=<link)(?=\s|>)/i', ' ' . AMP_Rule_Spec::DEV_MODE_ATTRIBUTE, $tag );
15691586
}
15701587
return $tag;
15711588
}
15721589

15731590
/**
1574-
* Add data-ampdevmode attribute to any enqueued script that depends on the admin-bar.
1591+
* Add data-ampdevmode attribute to any enqueued script that is flagged for dev mode or which depends on the admin-bar.
15751592
*
1576-
* @since 1.3
1593+
* @since 1.5
15771594
*
15781595
* @param string $tag The `<script>` tag for the enqueued script.
15791596
* @param string $handle The script's registered handle.
15801597
* @return string Tag.
15811598
*/
1582-
public static function filter_admin_bar_script_loader_tag( $tag, $handle ) {
1583-
if (
1584-
in_array( $handle, wp_scripts()->registered['admin-bar']->deps, true ) ?
1585-
self::is_exclusively_dependent( wp_scripts(), $handle, 'admin-bar' ) :
1586-
self::has_dependency( wp_scripts(), $handle, 'admin-bar' )
1587-
) {
1599+
public static function filter_script_loader_tag_for_dev_mode( $tag, $handle ) {
1600+
if ( self::dependency_needs_dev_mode( wp_scripts(), $handle ) ) {
15881601
$tag = preg_replace( '/(?<=<script)(?=\s|>)/i', ' ' . AMP_Rule_Spec::DEV_MODE_ATTRIBUTE, $tag );
15891602
}
15901603
return $tag;
@@ -2467,23 +2480,26 @@ public static function setup_paired_browsing_client() {
24672480
$asset = require $asset_file;
24682481
$dependencies = $asset['dependencies'];
24692482
$version = $asset['version'];
2483+
$handle = 'amp-paired-browsing-client';
24702484

24712485
wp_enqueue_script(
2472-
'amp-paired-browsing-client',
2486+
$handle,
24732487
amp_get_asset_url( '/js/amp-paired-browsing-client.js' ),
24742488
$dependencies,
24752489
$version,
24762490
true
24772491
);
2492+
wp_script_add_data( $handle, 'ampdevmode', true );
2493+
foreach ( $dependencies as $dependency ) {
2494+
wp_script_add_data( $dependency, 'ampdevmode', true );
2495+
}
24782496

2479-
// Whitelist enqueued script for AMP dev mdoe so that it is not removed.
2480-
// @todo Revisit with <https://github.com/google/site-kit-wp/pull/505#discussion_r348683617>.
24812497
add_filter(
24822498
'script_loader_tag',
2483-
static function( $tag, $handle ) {
2484-
if ( is_amp_endpoint() && self::has_dependency( wp_scripts(), 'amp-paired-browsing-client', $handle ) ) {
2485-
$attrs = [ AMP_Rule_Spec::DEV_MODE_ATTRIBUTE, 'async' ];
2486-
$tag = preg_replace( '/(?<=<script)(?=\s|>)/i', ' ' . implode( ' ', $attrs ), $tag );
2499+
static function( $tag, $filtered_handle ) use ( $handle ) {
2500+
if ( is_amp_endpoint() && self::has_dependency( wp_scripts(), $handle, $filtered_handle ) ) {
2501+
// Inject async attribute into script tag.
2502+
$tag = preg_replace( '/(<script[^>]*)(?=\ssrc=)/i', '$1 async ', $tag );
24872503
}
24882504
return $tag;
24892505
},

tests/php/test-amp-helper-functions.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -790,7 +790,6 @@ function ( $xpaths ) use ( $element_xpaths ) {
790790
[
791791
'//*[ @id = "wpadminbar" ]',
792792
'//*[ @id = "wpadminbar" ]//*',
793-
'//style[ @id = "admin-bar-inline-css" ]',
794793
]
795794
),
796795
$sanitizers['AMP_Dev_Mode_Sanitizer']['element_xpaths']

tests/php/test-class-amp-theme-support.php

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -996,6 +996,8 @@ static function( $templates ) {
996996
* @covers AMP_Theme_Support::add_hooks()
997997
*/
998998
public function test_add_hooks() {
999+
add_theme_support( 'amp' );
1000+
$this->go_to( '/' );
9991001
AMP_Theme_Support::add_hooks();
10001002
$this->assertFalse( has_action( 'wp_head', 'wp_post_preview_js' ) );
10011003
$this->assertFalse( has_action( 'wp_head', 'wp_oembed_add_host_js' ) );
@@ -1016,6 +1018,8 @@ public function test_add_hooks() {
10161018
$this->assertEquals( 10, has_filter( 'customize_partial_render', [ self::TESTED_CLASS, 'filter_customize_partial_render' ] ) );
10171019
$this->assertEquals( 10, has_action( 'wp_footer', 'amp_print_analytics' ) );
10181020
$this->assertEquals( 10, has_action( 'admin_bar_init', [ self::TESTED_CLASS, 'init_admin_bar' ] ) );
1021+
$this->assertEquals( 10, has_filter( 'style_loader_tag', [ 'AMP_Theme_Support', 'filter_style_loader_tag_for_dev_mode' ] ) );
1022+
$this->assertEquals( 10, has_filter( 'script_loader_tag', [ 'AMP_Theme_Support', 'filter_script_loader_tag_for_dev_mode' ] ) );
10191023
$priority = defined( 'PHP_INT_MIN' ) ? PHP_INT_MIN : ~PHP_INT_MAX; // phpcs:ignore PHPCompatibility.Constants.NewConstants.php_int_minFound
10201024
$this->assertEquals( $priority, has_action( 'template_redirect', [ self::TESTED_CLASS, 'start_output_buffering' ] ) );
10211025

@@ -1237,8 +1241,8 @@ public function test_filter_cancel_comment_reply_link() {
12371241
* Test init_admin_bar.
12381242
*
12391243
* @covers \AMP_Theme_Support::init_admin_bar()
1240-
* @covers \AMP_Theme_Support::filter_admin_bar_style_loader_tag()
1241-
* @covers \AMP_Theme_Support::filter_admin_bar_script_loader_tag()
1244+
* @covers \AMP_Theme_Support::filter_style_loader_tag_for_dev_mode()
1245+
* @covers \AMP_Theme_Support::filter_script_loader_tag_for_dev_mode()
12421246
*/
12431247
public function test_init_admin_bar() {
12441248
require_once ABSPATH . WPINC . '/class-wp-admin-bar.php';
@@ -1269,8 +1273,7 @@ function() {
12691273
$this->assertEquals( 10, has_action( 'wp_head', $callback ) );
12701274

12711275
AMP_Theme_Support::init_admin_bar();
1272-
$this->assertEquals( 10, has_filter( 'style_loader_tag', [ 'AMP_Theme_Support', 'filter_admin_bar_style_loader_tag' ] ) );
1273-
$this->assertEquals( 10, has_filter( 'script_loader_tag', [ 'AMP_Theme_Support', 'filter_admin_bar_script_loader_tag' ] ) );
1276+
AMP_Theme_Support::add_hooks();
12741277
$this->assertFalse( has_action( 'wp_head', $callback ) );
12751278
ob_start();
12761279
wp_print_styles();
@@ -1310,7 +1313,10 @@ public function assert_queried_element_exists( DOMXPath $xpath, $query ) {
13101313
public function assert_dev_mode_is_on_queried_element( DOMXPath $xpath, $query ) {
13111314
$element = $xpath->query( $query )->item( 0 );
13121315
$this->assertInstanceOf( 'DOMElement', $element, 'Expected element for query: ' . $query );
1313-
$this->assertTrue( $element->hasAttribute( AMP_Rule_Spec::DEV_MODE_ATTRIBUTE ), 'Expected dev mode to be enabled on element for query: ' . $query );
1316+
$this->assertTrue(
1317+
$element->hasAttribute( AMP_Rule_Spec::DEV_MODE_ATTRIBUTE ),
1318+
'Expected dev mode to be enabled on element for query: ' . $query . "\nDocument: " . $element->ownerDocument->saveHTML()
1319+
);
13141320
}
13151321

13161322
/**
@@ -1326,7 +1332,7 @@ public function assert_dev_mode_is_not_on_queried_element( DOMXPath $xpath, $que
13261332
}
13271333

13281334
/**
1329-
* Get data to test AMP_Theme_Support::filter_admin_bar_style_loader_tag().
1335+
* Get data to test AMP_Theme_Support::filter_style_loader_tag_for_dev_mode().
13301336
*
13311337
* @return array
13321338
*/
@@ -1396,10 +1402,10 @@ function ( DOMXPath $xpath ) {
13961402
}
13971403

13981404
/**
1399-
* Test filter_admin_bar_style_loader_tag.
1405+
* Test filter_style_loader_tag_for_dev_mode.
14001406
*
14011407
* @dataProvider get_data_to_test_filtering_admin_bar_style_loader_tag_data
1402-
* @covers \AMP_Theme_Support::filter_admin_bar_style_loader_tag()
1408+
* @covers \AMP_Theme_Support::filter_style_loader_tag_for_dev_mode()
14031409
* @covers \AMP_Theme_Support::is_exclusively_dependent()
14041410
*
14051411
* @param callable $setup_callback Setup callback.
@@ -1409,7 +1415,7 @@ public function test_filter_admin_bar_style_loader_tag( $setup_callback, $assert
14091415
add_theme_support( 'amp' );
14101416
$this->go_to( '/' );
14111417
add_filter( 'amp_dev_mode_enabled', '__return_true' );
1412-
add_filter( 'style_loader_tag', [ 'AMP_Theme_Support', 'filter_admin_bar_style_loader_tag' ], 10, 2 );
1418+
add_filter( 'style_loader_tag', [ 'AMP_Theme_Support', 'filter_style_loader_tag_for_dev_mode' ], 10, 2 );
14131419
$setup_callback();
14141420
ob_start();
14151421
echo '<html><head>';
@@ -1424,7 +1430,7 @@ public function test_filter_admin_bar_style_loader_tag( $setup_callback, $assert
14241430
}
14251431

14261432
/**
1427-
* Get data to test AMP_Theme_Support::filter_admin_bar_script_loader_tag().
1433+
* Get data to test AMP_Theme_Support::filter_script_loader_tag_for_dev_mode().
14281434
*
14291435
* @return array
14301436
*/
@@ -1434,10 +1440,14 @@ public function get_data_to_test_filtering_admin_bar_script_loader_tag_data() {
14341440
static function () {
14351441
wp_enqueue_script( 'admin-bar' );
14361442
wp_enqueue_script( 'example-admin-bar', 'https://example.com/example-admin-bar.js', [ 'admin-bar' ], '0.1', false );
1443+
wp_add_inline_script( 'example-admin-bar', '/* inline-example-admin-bar */' );
1444+
wp_localize_script( 'example-admin-bar', 'exampleAdminBar', [ 'hello' => 'world' ] );
14371445
},
14381446
function ( DOMXPath $xpath ) {
14391447
$this->assert_dev_mode_is_on_queried_element( $xpath, '//script[ contains( @src, "/example-admin-bar" ) ]' );
14401448
$this->assert_dev_mode_is_on_queried_element( $xpath, '//script[ contains( @src, "/admin-bar" ) ]' );
1449+
$this->assert_dev_mode_is_on_queried_element( $xpath, '//script[ contains( text(), "inline-example-admin-bar" ) ]' );
1450+
$this->assert_dev_mode_is_on_queried_element( $xpath, '//script[ contains( text(), "exampleAdminBar" ) ]' );
14411451
if ( wp_script_is( 'hoverintent-js', 'registered' ) ) {
14421452
$this->assert_dev_mode_is_on_queried_element( $xpath, '//script[ contains( @src, "/hoverintent-js" ) ]' );
14431453
}
@@ -1496,10 +1506,10 @@ function ( DOMXPath $xpath ) {
14961506
}
14971507

14981508
/**
1499-
* Test filter_admin_bar_script_loader_tag.
1509+
* Test filter_script_loader_tag_for_dev_mode.
15001510
*
15011511
* @dataProvider get_data_to_test_filtering_admin_bar_script_loader_tag_data
1502-
* @covers \AMP_Theme_Support::filter_admin_bar_script_loader_tag()
1512+
* @covers \AMP_Theme_Support::filter_script_loader_tag_for_dev_mode()
15031513
* @covers \AMP_Theme_Support::is_exclusively_dependent()
15041514
*
15051515
* @param callable $setup_callback Setup callback.
@@ -1509,7 +1519,7 @@ public function test_filter_admin_bar_script_loader_tag( $setup_callback, $asser
15091519
add_theme_support( 'amp' );
15101520
$this->go_to( '/' );
15111521
add_filter( 'amp_dev_mode_enabled', '__return_true' );
1512-
add_filter( 'script_loader_tag', [ 'AMP_Theme_Support', 'filter_admin_bar_script_loader_tag' ], 10, 2 );
1522+
add_filter( 'script_loader_tag', [ 'AMP_Theme_Support', 'filter_script_loader_tag_for_dev_mode' ], 10, 2 );
15131523
$setup_callback();
15141524
ob_start();
15151525
echo '<html><head>';
@@ -1519,8 +1529,14 @@ public function test_filter_admin_bar_script_loader_tag( $setup_callback, $asser
15191529
echo '</body></html>';
15201530
$output = ob_get_clean();
15211531

1522-
$dom = new DOMDocument();
1523-
@$dom->loadHTML( $output ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
1532+
$dom = new Document();
1533+
$dom->loadHTML( $output );
1534+
1535+
AMP_Content_Sanitizer::sanitize_document(
1536+
$dom,
1537+
wp_array_slice_assoc( amp_get_content_sanitizers(), [ 'AMP_Dev_Mode_Sanitizer' ] ),
1538+
[ 'use_document_element' => true ]
1539+
);
15241540

15251541
$assert_callback( new DOMXPath( $dom ) );
15261542
}
@@ -1529,15 +1545,18 @@ public function test_filter_admin_bar_script_loader_tag( $setup_callback, $asser
15291545
* Test init_admin_bar to ensure dashicons are not added to dev mode when directly enqueued.
15301546
*
15311547
* @covers \AMP_Theme_Support::init_admin_bar()
1532-
* @covers \AMP_Theme_Support::filter_admin_bar_style_loader_tag()
1548+
* @covers \AMP_Theme_Support::filter_style_loader_tag_for_dev_mode()
15331549
*/
15341550
public function test_init_admin_bar_for_directly_enqueued_dashicons() {
1551+
add_theme_support( 'amp' );
1552+
$this->go_to( '/' );
15351553
require_once ABSPATH . WPINC . '/class-wp-admin-bar.php';
15361554

15371555
global $wp_admin_bar;
15381556
$wp_admin_bar = new WP_Admin_Bar();
15391557
$wp_admin_bar->initialize();
15401558
AMP_Theme_Support::init_admin_bar();
1559+
AMP_Theme_Support::add_hooks();
15411560

15421561
// Enqueued directly.
15431562
wp_enqueue_style( 'dashicons' );
@@ -1555,15 +1574,18 @@ public function test_init_admin_bar_for_directly_enqueued_dashicons() {
15551574
* Test init_admin_bar to ensure dashicons are not added to dev mode when indirectly enqueued.
15561575
*
15571576
* @covers \AMP_Theme_Support::init_admin_bar()
1558-
* @covers \AMP_Theme_Support::filter_admin_bar_style_loader_tag()
1577+
* @covers \AMP_Theme_Support::filter_style_loader_tag_for_dev_mode()
15591578
*/
15601579
public function test_init_admin_bar_for_indirectly_enqueued_dashicons() {
1580+
add_theme_support( 'amp' );
1581+
$this->go_to( '/' );
15611582
require_once ABSPATH . WPINC . '/class-wp-admin-bar.php';
15621583

15631584
global $wp_admin_bar;
15641585
$wp_admin_bar = new WP_Admin_Bar();
15651586
$wp_admin_bar->initialize();
15661587
AMP_Theme_Support::init_admin_bar();
1588+
AMP_Theme_Support::add_hooks();
15671589

15681590
// Enqueued indirectly.
15691591
wp_enqueue_style( 'my-font-pack', 'https://example.com/fonts', [ 'dashicons' ], '0.1' );

0 commit comments

Comments
 (0)