Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ampify responsive Navigation Block #6838

Merged
merged 14 commits into from
Jan 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
137 changes: 137 additions & 0 deletions includes/embeds/class-amp-core-block-handler.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ class AMP_Core_Block_Handler extends AMP_Base_Embed_Handler {
*/
private $category_widget_count = 0;

/**
* Count of the navigation blocks encountered.
*
* @var int
*/
private $navigation_block_count = 0;

/**
* Methods to ampify blocks.
*
Expand All @@ -51,6 +58,7 @@ class AMP_Core_Block_Handler extends AMP_Base_Embed_Handler {
'core/archives' => 'ampify_archives_block',
'core/video' => 'ampify_video_block',
'core/file' => 'ampify_file_block',
'core/navigation' => 'ampify_navigation_block',
];

/**
Expand Down Expand Up @@ -269,6 +277,135 @@ public function dequeue_block_library_file_script() {
wp_dequeue_script( 'wp-block-library-file' );
}

/**
* Ampify navigation block contained by <nav> element.
*
* @since 2.2.1
*
* @param string $block_content The block content about to be appended.
* @param array $block The full block, including name and attributes.
*
* @return string Filtered block content.
*/
public function ampify_navigation_block( $block_content, $block ) {
if ( 0 === $this->navigation_block_count ) {
add_action( 'wp_print_scripts', [ $this, 'dequeue_block_navigation_view_script' ], 0 );
add_action( 'wp_print_footer_scripts', [ $this, 'dequeue_block_navigation_view_script' ], 0 );
}

$this->navigation_block_count++;
$modal_state_property = "modal_{$this->navigation_block_count}_expanded";

// Set `aria-expanded` value of submenus whenever AMP state changes.
$submenu_toggles_count = 0;
$block_content = preg_replace_callback(
'/(?<=<button)\s[^>]+/',
static function ( $matches ) use ( $modal_state_property, &$submenu_toggles_count ) {
$new_block_content = $matches[0];

if ( false === strpos( $new_block_content, 'wp-block-navigation-submenu__toggle' ) ) {
return $new_block_content;
}

$submenu_toggles_count++;

$submenu_state_property = str_replace(
'expanded',
'submenu_' . $submenu_toggles_count . '_expanded',
$modal_state_property
);

// Set `aria-expanded` value of submenus whenever AMP state changes.
return str_replace(
' aria-expanded',
sprintf(
' on="tap:AMP.setState({ %1$s: !%1$s })" [aria-expanded]="%1$s ? \'true\' : \'false\'" aria-expanded',
esc_attr( $submenu_state_property )
),
$new_block_content
);
},
$block_content
);

// In case of the "Mobile" option value, the `overlayMenu` attribute is not set at all.
if ( ! empty( $block['attrs']['overlayMenu'] ) && 'never' === $block['attrs']['overlayMenu'] ) {
return $block_content;
}

// Replace micromodal toggle logic with AMP state and set modal state property name based on its ID.
$block_content = preg_replace(
'/\sdata-micromodal-trigger="modal-\w+"/',
sprintf( ' on="tap:AMP.setState({ %1$s: !%1$s })"', esc_attr( $modal_state_property ) ),
$block_content
);

$block_content = preg_replace_callback(
'/(?<=<button)\s[^>]+/',
static function ( $matches ) use ( $modal_state_property ) {
$new_block_content = $matches[0];

// Skip submenu toggles.
if ( false !== strpos( $new_block_content, 'wp-block-navigation-submenu__toggle' ) ) {
return $new_block_content;
}

// Replace micromodal toggle logic bound with buttons with AMP state.
if ( false !== strpos( $new_block_content, ' data-micromodal-close' ) ) {
$new_block_content = str_replace(
' data-micromodal-close',
sprintf( ' on="tap:AMP.setState({ %1$s: !%1$s })"', esc_attr( $modal_state_property ) ),
$new_block_content
);
}

// Set `aria-expanded` value whenever AMP state changes.
return str_replace(
' aria-expanded',
sprintf(
' [aria-expanded]="%s ? \'true\' : \'false\'" aria-expanded',
esc_attr( $modal_state_property )
),
$new_block_content
);
},
$block_content
);

// Delete other micromodal-related data attributes.
$block_content = preg_replace( '/\sdata-micromodal-close/', '', $block_content );

// Change a responsive container class name and aria-hidden value based on the AMP state.
$block_content = preg_replace_callback(
'/(?><.+\sclass="([^"]*wp-block-navigation__responsive-container(?>\s[^"]*)?)"[^>]*>)/',
static function ( $matches ) use ( $modal_state_property ) {
$new_block_content = str_replace(
' class=',
sprintf(
' [aria-hidden]="%1$s ? \'false\' : \'true\'" aria-hidden="true" [class]="%1$s ? \'%2$s is-menu-open has-modal-open\' : \'%2$s\'" class=',
esc_attr( $modal_state_property ),
esc_attr( $matches[1] )
),
$matches[0]
);

return $new_block_content;
},
$block_content
);

return $block_content;
}

/**
* Dequeue wp-block-navigation-view script.
*
* @since 2.2.1
*/
public function dequeue_block_navigation_view_script() {
wp_dequeue_script( 'wp-block-navigation-view' );
}

/**
* Sanitize widgets that are not added via Gutenberg.
*
Expand Down
Loading