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

HTML API: Introduce HTML templating #12

Closed
wants to merge 16 commits into from
Closed
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
2 changes: 1 addition & 1 deletion src/wp-content/themes/twentytwentyfour/theme.json
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@
{
"fontFamily": "Iowan Old Style, Apple Garamond, Baskerville, Times New Roman, Droid Serif, Times, Source Serif Pro, serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol",
"name": "System Serif",
"slug": "system-Serif"
"slug": "system-serif"
}
],
"fontSizes": [
Expand Down
14 changes: 14 additions & 0 deletions src/wp-includes/block-patterns.php
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,20 @@ function _register_core_block_patterns_and_categories() {
'description' => __( 'Different layouts containing video or audio.' ),
)
);
register_block_pattern_category(
'videos',
array(
'label' => _x( 'Videos', 'Block pattern category' ),
'description' => __( 'Different layouts containing videos.' ),
)
);
register_block_pattern_category(
'audio',
array(
'label' => _x( 'Audio', 'Block pattern category' ),
'description' => __( 'Different layouts containing audio.' ),
)
);
register_block_pattern_category(
'posts',
array(
Expand Down
2 changes: 1 addition & 1 deletion src/wp-includes/block-template-utils.php
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ function _get_block_templates_paths( $base_directory ) {
* @param string $template_type 'wp_template' or 'wp_template_part'.
* @param string $slug Template slug.
* @return array|null {
* Array with template metadata if $template_type is one of 'wp_template' or 'wp_template_part'.
* Array with template metadata if $template_type is one of 'wp_template' or 'wp_template_part',
* null otherwise.
*
* @type string $slug Template slug.
Expand Down
143 changes: 80 additions & 63 deletions src/wp-includes/blocks.php
Original file line number Diff line number Diff line change
Expand Up @@ -758,22 +758,28 @@ function get_hooked_blocks() {
}

/**
* Conditionally returns the markup for a given hooked block type.
* Conditionally returns the markup for a given hooked block.
*
* Accepts two arguments: A reference to an anchor block, and the name of a hooked block type.
* Accepts three arguments: A hooked block, its type, and a reference to an anchor block.
* If the anchor block has already been processed, and the given hooked block type is in the list
* of ignored hooked blocks, an empty string is returned.
*
* The hooked block type is specified separately as it's possible that a filter might've modified
* the hooked block such that `$hooked_block['blockName']` does no longer reflect the original type.
*
* This function is meant for internal use only.
*
* @since 6.5.0
* @access private
*
* @param array $anchor_block The anchor block. Passed by reference.
* @param string $hooked_block_type The name of the hooked block type.
* @return string The markup for the given hooked block type, or an empty string if the block is ignored.
* @param array $hooked_block The hooked block, represented as a parsed block array.
* @param string $hooked_block_type The type of the hooked block. This could be different from
* $hooked_block['blockName'], as a filter might've modified the latter.
* @param array $anchor_block The anchor block, represented as a parsed block array.
* Passed by reference.
* @return string The markup for the given hooked block, or an empty string if the block is ignored.
*/
function get_hooked_block_markup( &$anchor_block, $hooked_block_type ) {
function get_hooked_block_markup( $hooked_block, $hooked_block_type, &$anchor_block ) {
if ( ! isset( $anchor_block['attrs']['metadata']['ignoredHookedBlocks'] ) ) {
$anchor_block['attrs']['metadata']['ignoredHookedBlocks'] = array();
}
Expand All @@ -786,7 +792,70 @@ function get_hooked_block_markup( &$anchor_block, $hooked_block_type ) {
// However, its presence does not affect the frontend.
$anchor_block['attrs']['metadata']['ignoredHookedBlocks'][] = $hooked_block_type;

return get_comment_delimited_block_content( $hooked_block_type, array(), '' );
return serialize_block( $hooked_block );
}

/**
* Returns the markup for blocks hooked to the given anchor block in a specific relative position.
*
* @since 6.5.0
* @access private
*
* @param array $parsed_anchor_block The anchor block, in parsed block array format.
* @param string $relative_position The relative position of the hooked blocks.
* Can be one of 'before', 'after', 'first_child', or 'last_child'.
* @param array $hooked_blocks An array of hooked block types, grouped by anchor block and relative position.
* @param WP_Block_Template|array $context The block template, template part, or pattern that the anchor block belongs to.
* @return string
*/
function insert_hooked_blocks( &$parsed_anchor_block, $relative_position, $hooked_blocks, $context ) {
$anchor_block_type = $parsed_anchor_block['blockName'];
$hooked_block_types = isset( $hooked_blocks[ $anchor_block_type ][ $relative_position ] )
? $hooked_blocks[ $anchor_block_type ][ $relative_position ]
: array();

/**
* Filters the list of hooked block types for a given anchor block type and relative position.
*
* @since 6.4.0
*
* @param string[] $hooked_block_types The list of hooked block types.
* @param string $relative_position The relative position of the hooked blocks.
* Can be one of 'before', 'after', 'first_child', or 'last_child'.
* @param string $anchor_block_type The anchor block type.
* @param WP_Block_Template|array $context The block template, template part, or pattern that the anchor block belongs to.
*/
$hooked_block_types = apply_filters( 'hooked_block_types', $hooked_block_types, $relative_position, $anchor_block_type, $context );

$markup = '';
foreach ( $hooked_block_types as $hooked_block_type ) {
$parsed_hooked_block = array(
'blockName' => $hooked_block_type,
'attrs' => array(),
'innerBlocks' => array(),
'innerContent' => array(),
);

/**
* Filters the parsed block array for a given hooked block.
*
* The dynamic portion of the hook name, `$hooked_block_type`, refers to the block type name of the specific hooked block.
*
* @since 6.5.0
*
* @param array $parsed_hooked_block The parsed block array for the given hooked block type.
* @param string $relative_position The relative position of the hooked block.
* @param array $parsed_anchor_block The anchor block, in parsed block array format.
* @param WP_Block_Template|array $context The block template, template part, or pattern that the anchor block belongs to.
*/
$parsed_hooked_block = apply_filters( "hooked_block_{$hooked_block_type}", $parsed_hooked_block, $relative_position, $parsed_anchor_block, $context );

// It's possible that the `hooked_block_{$hooked_block_type}` filter returned a block of a different type,
// so we need to pass the original $hooked_block_type as well.
$markup .= get_hooked_block_markup( $parsed_hooked_block, $hooked_block_type, $parsed_anchor_block );
}

return $markup;
}

/**
Expand Down Expand Up @@ -826,40 +895,10 @@ function make_before_block_visitor( $hooked_blocks, $context ) {

if ( $parent_block && ! $prev ) {
// Candidate for first-child insertion.
$relative_position = 'first_child';
$anchor_block_type = $parent_block['blockName'];
$hooked_block_types = isset( $hooked_blocks[ $anchor_block_type ][ $relative_position ] )
? $hooked_blocks[ $anchor_block_type ][ $relative_position ]
: array();

/**
* Filters the list of hooked block types for a given anchor block type and relative position.
*
* @since 6.4.0
*
* @param string[] $hooked_block_types The list of hooked block types.
* @param string $relative_position The relative position of the hooked blocks.
* Can be one of 'before', 'after', 'first_child', or 'last_child'.
* @param string $anchor_block_type The anchor block type.
* @param WP_Block_Template|array $context The block template, template part, or pattern that the anchor block belongs to.
*/
$hooked_block_types = apply_filters( 'hooked_block_types', $hooked_block_types, $relative_position, $anchor_block_type, $context );
foreach ( $hooked_block_types as $hooked_block_type ) {
$markup .= get_hooked_block_markup( $parent_block, $hooked_block_type );
}
$markup .= insert_hooked_blocks( $parent_block, 'first_child', $hooked_blocks, $context );
}

$relative_position = 'before';
$anchor_block_type = $block['blockName'];
$hooked_block_types = isset( $hooked_blocks[ $anchor_block_type ][ $relative_position ] )
? $hooked_blocks[ $anchor_block_type ][ $relative_position ]
: array();

/** This filter is documented in wp-includes/blocks.php */
$hooked_block_types = apply_filters( 'hooked_block_types', $hooked_block_types, $relative_position, $anchor_block_type, $context );
foreach ( $hooked_block_types as $hooked_block_type ) {
$markup .= get_hooked_block_markup( $block, $hooked_block_type );
}
$markup .= insert_hooked_blocks( $block, 'before', $hooked_blocks, $context );

return $markup;
};
Expand Down Expand Up @@ -895,33 +934,11 @@ function make_after_block_visitor( $hooked_blocks, $context ) {
* @return string The serialized markup for the given block, with the markup for any hooked blocks appended to it.
*/
return function ( &$block, &$parent_block = null, $next = null ) use ( $hooked_blocks, $context ) {
$markup = '';

$relative_position = 'after';
$anchor_block_type = $block['blockName'];
$hooked_block_types = isset( $hooked_blocks[ $anchor_block_type ][ $relative_position ] )
? $hooked_blocks[ $anchor_block_type ][ $relative_position ]
: array();

/** This filter is documented in wp-includes/blocks.php */
$hooked_block_types = apply_filters( 'hooked_block_types', $hooked_block_types, $relative_position, $anchor_block_type, $context );
foreach ( $hooked_block_types as $hooked_block_type ) {
$markup .= get_hooked_block_markup( $block, $hooked_block_type );
}
$markup = insert_hooked_blocks( $block, 'after', $hooked_blocks, $context );

if ( $parent_block && ! $next ) {
// Candidate for last-child insertion.
$relative_position = 'last_child';
$anchor_block_type = $parent_block['blockName'];
$hooked_block_types = isset( $hooked_blocks[ $anchor_block_type ][ $relative_position ] )
? $hooked_blocks[ $anchor_block_type ][ $relative_position ]
: array();

/** This filter is documented in wp-includes/blocks.php */
$hooked_block_types = apply_filters( 'hooked_block_types', $hooked_block_types, $relative_position, $anchor_block_type, $context );
foreach ( $hooked_block_types as $hooked_block_type ) {
$markup .= get_hooked_block_markup( $parent_block, $hooked_block_type );
}
$markup .= insert_hooked_blocks( $parent_block, 'last_child', $hooked_blocks, $context );
}

return $markup;
Expand Down
110 changes: 61 additions & 49 deletions src/wp-includes/blocks/image.php
Original file line number Diff line number Diff line change
Expand Up @@ -229,26 +229,32 @@ function block_core_image_render_lightbox( $block_content, $block ) {
$body_content = $w->get_updated_html();

// Add a button alongside image in the body content.
$img = null;
preg_match( '/<img[^>]+>/', $body_content, $img );

$button =
$img[0]
. '<button
class="lightbox-trigger"
type="button"
aria-haspopup="dialog"
aria-label="' . esc_attr( $aria_label ) . '"
data-wp-on--click="actions.core.image.showLightbox"
data-wp-style--right="context.core.image.imageButtonRight"
data-wp-style--top="context.core.image.imageButtonTop"
>
<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
</svg>
</button>';

$body_content = preg_replace( '/<img[^>]+>/', $button, $body_content );
$body_content = preg_replace_callback(
'/<img[^>]+>/',
static function ( $img_match ) use ( $aria_label ) {
$button_html = WP_HTML::render(
<<<'HTML'
<button class="lightbox-trigger" type="button" aria-haspopup="dialog" aria-label="</%label>" ...interactivity>
<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
</svg>
</button>
HTML,
array(
'label' => $aria_label,
'interactivity' => array(
'data-wp-on--click' => 'actions.core.image.showLightbox',
'data-wp-style--right' => 'context.core.image.imageButtonRight',
'data-wp-style--top' => 'context.core.image.imageButtonTop',
),
)
);

return $img_match[0] . $button_html;
},
$body_content,
1
);

// We need both a responsive image and an enlarged image to animate
// the zoom seamlessly on slow internet connections; the responsive
Expand Down Expand Up @@ -295,40 +301,46 @@ class="lightbox-trigger"
if ( wp_theme_has_theme_json() ) {
$global_styles_color = wp_get_global_styles( array( 'color' ) );
if ( ! empty( $global_styles_color['background'] ) ) {
$background_color = esc_attr( $global_styles_color['background'] );
$background_color = $global_styles_color['background'];
}
if ( ! empty( $global_styles_color['text'] ) ) {
$close_button_color = esc_attr( $global_styles_color['text'] );
$close_button_color = $global_styles_color['text'];
}
}

$close_button_icon = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="20" height="20" aria-hidden="true" focusable="false"><path d="M13 11.8l6.1-6.3-1-1-6.1 6.2-6.1-6.2-1 1 6.1 6.3-6.5 6.7 1 1 6.5-6.6 6.5 6.6 1-1z"></path></svg>';
$close_button_label = esc_attr__( 'Close' );

$lightbox_html = <<<HTML
<div data-wp-body="" class="wp-lightbox-overlay $lightbox_animation"
data-wp-bind--role="selectors.core.image.roleAttribute"
data-wp-bind--aria-label="selectors.core.image.dialogLabel"
data-wp-class--initialized="context.core.image.initialized"
data-wp-class--active="context.core.image.lightboxEnabled"
data-wp-class--hideAnimationEnabled="context.core.image.hideAnimationEnabled"
data-wp-bind--aria-modal="selectors.core.image.ariaModal"
data-wp-effect="effects.core.image.initLightbox"
data-wp-on--keydown="actions.core.image.handleKeydown"
data-wp-on--touchstart="actions.core.image.handleTouchStart"
data-wp-on--touchmove="actions.core.image.handleTouchMove"
data-wp-on--touchend="actions.core.image.handleTouchEnd"
data-wp-on--click="actions.core.image.hideLightbox"
tabindex="-1"
>
<button type="button" aria-label="$close_button_label" style="fill: $close_button_color" class="close-button" data-wp-on--click="actions.core.image.hideLightbox">
$close_button_icon
</button>
<div class="lightbox-image-container">$initial_image_content</div>
<div class="lightbox-image-container">$enlarged_image_content</div>
<div class="scrim" style="background-color: $background_color" aria-hidden="true"></div>
</div>
HTML;
$lightbox_html = WP_HTML::render(
<<<HTML
<div class="wp-lightbox-overlay </%lightbox_animation_class>" tabindex="-1" ...interactivity>
<button type="button" aria-label="</%close_label>" style="fill: </%close_button_color>" class="close-button" data-wp-on--click="actions.core.image.hideLightbox">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="20" height="20" aria-hidden="true" focusable="false"><path d="M13 11.8l6.1-6.3-1-1-6.1 6.2-6.1-6.2-1 1 6.1 6.3-6.5 6.7 1 1 6.5-6.6 6.5 6.6 1-1z"></path></svg>
</button>
<div class="lightbox-image-container">$initial_image_content</div>
<div class="lightbox-image-container">$enlarged_image_content</div>
<div class="scrim" style="background-color: </%background_color>" aria-hidden="true"></div>
</div>
HTML,
array(
'background_color' => $background_color,
'close_button_color' => $close_button_color,
'close_label' => __( 'Close' ),
'lightbox_animation_class' => $lightbox_animation,
'interactivity' => array(
'data-wp-bind--role' => 'selectors.core.image.roleAttribute',
'data-wp-bind--aria-label' => 'selectors.core.image.dialogLabel',
'data-wp-body' => '',
'data-wp-class--initialized' => 'context.core.image.initialized',
'data-wp-class--active' => 'context.core.image.lightboxEnabled',
'data-wp-class--hideAnimationEnabled' => 'context.core.image.hideAnimationEnabled',
'data-wp-bind--aria-modal' => 'selectors.core.image.ariaModal',
'data-wp-effect' => 'effects.core.image.initLightbox',
'data-wp-on--keydown' => 'actions.core.image.handleKeydown',
'data-wp-on--touchstart' => 'actions.core.image.handleTouchStart',
'data-wp-on--touchmove' => 'actions.core.image.handleTouchMove',
'data-wp-on--touchend' => 'actions.core.image.handleTouchEnd',
'data-wp-on--click' => 'actions.core.image.hideLightbox',
),
)
);

return str_replace( '</figure>', $lightbox_html . '</figure>', $body_content );
}
Expand Down
22 changes: 16 additions & 6 deletions src/wp-includes/canonical.php
Original file line number Diff line number Diff line change
Expand Up @@ -550,13 +550,23 @@ function redirect_canonical( $requested_url = null, $do_redirect = true ) {
$is_attachment_redirect = false;

if ( is_attachment() && ! get_option( 'wp_attachment_pages_enabled' ) ) {
$attachment_id = get_query_var( 'attachment_id' );

if ( current_user_can( 'read_post', $attachment_id ) ) {
$redirect_url = wp_get_attachment_url( $attachment_id );

$is_attachment_redirect = true;
$attachment_id = get_query_var( 'attachment_id' );
$attachment_post = get_post( $attachment_id );
$attachment_parent_id = $attachment_post ? $attachment_post->post_parent : 0;

$attachment_url = wp_get_attachment_url( $attachment_id );
if ( $attachment_url !== $redirect_url ) {
/*
* If an attachment is attached to a post, it inherits the parent post's status. Fetch the
* parent post to check its status later.
*/
if ( $attachment_parent_id ) {
$redirect_obj = get_post( $attachment_parent_id );
}
$redirect_url = $attachment_url;
}

$is_attachment_redirect = true;
}

$redirect['query'] = preg_replace( '#^\??&*?#', '', $redirect['query'] );
Expand Down
Loading