mirror of
git://develop.git.wordpress.org/
synced 2025-01-17 12:58:25 +01:00
Blocks: Parse blocks when displaying posts.
Posts containing blocks are now correctly handled when displaying on the front end, including dynamic blocks and nested blocks. Props pento. Merges [43752] to trunk. See #45109. git-svn-id: https://develop.svn.wordpress.org/trunk@44118 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
parent
6aef7e1966
commit
93091fac36
@ -113,6 +113,44 @@ function get_dynamic_block_names() {
|
||||
return $dynamic_block_names;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all dynamic blocks from the given content.
|
||||
*
|
||||
* @since 5.0.0
|
||||
*
|
||||
* @param string $content Content of the current post.
|
||||
* @return string
|
||||
*/
|
||||
function strip_dynamic_blocks( $content ) {
|
||||
return _recurse_strip_dynamic_blocks( parse_blocks( $content ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for strip_dynamic_blocks(), to recurse through the block tree.
|
||||
*
|
||||
* @since 5.0.0
|
||||
* @access private
|
||||
*
|
||||
* @param array $blocks Array of blocks from parse_blocks().
|
||||
* @return string HTML from the non-dynamic blocks.
|
||||
*/
|
||||
function _recurse_strip_dynamic_blocks( $blocks ) {
|
||||
$clean_content = '';
|
||||
$dynamic_blocks = get_dynamic_block_names();
|
||||
|
||||
foreach ( $blocks as $block ) {
|
||||
if ( ! in_array( $block['blockName'], $dynamic_blocks ) ) {
|
||||
if ( $block['innerBlocks'] ) {
|
||||
$clean_content .= _recurse_strip_dynamic_blocks( $block['innerBlocks'] );
|
||||
} else {
|
||||
$clean_content .= $block['innerHTML'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $clean_content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses blocks out of a content string.
|
||||
*
|
||||
@ -142,10 +180,85 @@ function parse_blocks( $content ) {
|
||||
*
|
||||
* @since 5.0.0
|
||||
*
|
||||
* @param string $parser_class Name of block parser class
|
||||
* @param string $parser_class Name of block parser class.
|
||||
*/
|
||||
$parser_class = apply_filters( 'block_parser_class', 'WP_Block_Parser' );
|
||||
|
||||
$parser = new $parser_class();
|
||||
return $parser->parse( $content );
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses dynamic blocks out of `post_content` and re-renders them.
|
||||
*
|
||||
* @since 5.0.0
|
||||
* @global WP_Post $post The post to edit.
|
||||
*
|
||||
* @param string $content Post content.
|
||||
* @return string Updated post content.
|
||||
*/
|
||||
function do_blocks( $content ) {
|
||||
$blocks = parse_blocks( $content );
|
||||
return _recurse_do_blocks( $blocks, $blocks );
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for do_blocks(), to recurse through the block tree.
|
||||
*
|
||||
* @since 5.0.0
|
||||
* @access private
|
||||
*
|
||||
* @param array $blocks Array of blocks from parse_blocks().
|
||||
* @param array $all_blocks The top level array of blocks.
|
||||
* @return string The block HTML.
|
||||
*/
|
||||
function _recurse_do_blocks( $blocks, $all_blocks ) {
|
||||
global $post;
|
||||
|
||||
/*
|
||||
* Back up global post, to restore after render callback.
|
||||
* Allows callbacks to run new WP_Query instances without breaking the global post.
|
||||
*/
|
||||
$global_post = $post;
|
||||
|
||||
$rendered_content = '';
|
||||
$dynamic_blocks = get_dynamic_block_names();
|
||||
|
||||
foreach ( $blocks as $block ) {
|
||||
$block = (array) $block;
|
||||
if ( in_array( $block['blockName'], $dynamic_blocks ) ) {
|
||||
// Find registered block type. We can assume it exists since we use the
|
||||
// `get_dynamic_block_names` function as a source for pattern matching.
|
||||
$block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] );
|
||||
|
||||
// Replace dynamic block with server-rendered output.
|
||||
$block_content = $block_type->render( (array) $block['attrs'], $block['innerHTML'] );
|
||||
} elseif ( $block['innerBlocks'] ) {
|
||||
$block_content = _recurse_do_blocks( $block['innerBlocks'], $blocks );
|
||||
} else {
|
||||
$block_content = $block['innerHTML'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the content of a single block.
|
||||
*
|
||||
* During the_content, each block is parsed and added to the output individually. This filter allows
|
||||
* that content to be altered immediately before it's appended.
|
||||
*
|
||||
* @since 5.0.0
|
||||
*
|
||||
* @param string $block_content The block content about to be appended.
|
||||
* @param array $block The full block, including name and attributes.
|
||||
* @param array $all_blocks The array of all blocks being processed.
|
||||
*/
|
||||
$rendered_content .= apply_filters( 'do_block', $block_content, $block, $all_blocks );
|
||||
|
||||
// Restore global $post.
|
||||
$post = $global_post;
|
||||
}
|
||||
|
||||
// Strip remaining block comment demarcations.
|
||||
$rendered_content = preg_replace( '/<!--\s+\/?wp:.*?-->/m', '', $rendered_content );
|
||||
|
||||
return $rendered_content;
|
||||
}
|
||||
|
143
src/wp-includes/blocks/archives.php
Normal file
143
src/wp-includes/blocks/archives.php
Normal file
@ -0,0 +1,143 @@
|
||||
<?php
|
||||
/**
|
||||
* Server-side rendering of the `core/archives` block.
|
||||
*
|
||||
* @package gutenberg
|
||||
*/
|
||||
|
||||
/**
|
||||
* Renders the `core/archives` block on server.
|
||||
*
|
||||
* @see WP_Widget_Archives
|
||||
*
|
||||
* @param array $attributes The block attributes.
|
||||
*
|
||||
* @return string Returns the post content with archives added.
|
||||
*/
|
||||
function render_block_core_archives( $attributes ) {
|
||||
$show_post_count = ! empty( $attributes['showPostCounts'] );
|
||||
|
||||
$class = 'wp-block-archives';
|
||||
|
||||
if ( isset( $attributes['align'] ) ) {
|
||||
$class .= " align{$attributes['align']}";
|
||||
}
|
||||
|
||||
if ( isset( $attributes['className'] ) ) {
|
||||
$class .= " {$attributes['className']}";
|
||||
}
|
||||
|
||||
if ( ! empty( $attributes['displayAsDropdown'] ) ) {
|
||||
|
||||
$dropdown_id = esc_attr( uniqid( 'wp-block-archives-' ) );
|
||||
$title = __( 'Archives', 'gutenberg' );
|
||||
|
||||
/** This filter is documented in wp-includes/widgets/class-wp-widget-archives.php */
|
||||
$dropdown_args = apply_filters(
|
||||
'widget_archives_dropdown_args',
|
||||
array(
|
||||
'type' => 'monthly',
|
||||
'format' => 'option',
|
||||
'show_post_count' => $show_post_count,
|
||||
)
|
||||
);
|
||||
|
||||
$dropdown_args['echo'] = 0;
|
||||
|
||||
$archives = wp_get_archives( $dropdown_args );
|
||||
|
||||
switch ( $dropdown_args['type'] ) {
|
||||
case 'yearly':
|
||||
$label = __( 'Select Year', 'gutenberg' );
|
||||
break;
|
||||
case 'monthly':
|
||||
$label = __( 'Select Month', 'gutenberg' );
|
||||
break;
|
||||
case 'daily':
|
||||
$label = __( 'Select Day', 'gutenberg' );
|
||||
break;
|
||||
case 'weekly':
|
||||
$label = __( 'Select Week', 'gutenberg' );
|
||||
break;
|
||||
default:
|
||||
$label = __( 'Select Post', 'gutenberg' );
|
||||
break;
|
||||
}
|
||||
|
||||
$label = esc_attr( $label );
|
||||
|
||||
$block_content = '<label class="screen-reader-text" for="' . $dropdown_id . '">' . $title . '</label>
|
||||
<select id="' . $dropdown_id . '" name="archive-dropdown" onchange="document.location.href=this.options[this.selectedIndex].value;">
|
||||
<option value="">' . $label . '</option>' . $archives . '</select>';
|
||||
|
||||
$block_content = sprintf(
|
||||
'<div class="%1$s">%2$s</div>',
|
||||
esc_attr( $class ),
|
||||
$block_content
|
||||
);
|
||||
} else {
|
||||
|
||||
/** This filter is documented in wp-includes/widgets/class-wp-widget-archives.php */
|
||||
$archives_args = apply_filters(
|
||||
'widget_archives_args',
|
||||
array(
|
||||
'type' => 'monthly',
|
||||
'show_post_count' => $show_post_count,
|
||||
)
|
||||
);
|
||||
|
||||
$archives_args['echo'] = 0;
|
||||
|
||||
$archives = wp_get_archives( $archives_args );
|
||||
|
||||
$classnames = esc_attr( $class );
|
||||
|
||||
if ( empty( $archives ) ) {
|
||||
|
||||
$block_content = sprintf(
|
||||
'<div class="%1$s">%2$s</div>',
|
||||
$classnames,
|
||||
__( 'No archives to show.', 'gutenberg' )
|
||||
);
|
||||
} else {
|
||||
|
||||
$block_content = sprintf(
|
||||
'<ul class="%1$s">%2$s</ul>',
|
||||
$classnames,
|
||||
$archives
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $block_content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register archives block.
|
||||
*/
|
||||
function register_block_core_archives() {
|
||||
register_block_type(
|
||||
'core/archives',
|
||||
array(
|
||||
'attributes' => array(
|
||||
'align' => array(
|
||||
'type' => 'string',
|
||||
),
|
||||
'className' => array(
|
||||
'type' => 'string',
|
||||
),
|
||||
'displayAsDropdown' => array(
|
||||
'type' => 'boolean',
|
||||
'default' => false,
|
||||
),
|
||||
'showPostCounts' => array(
|
||||
'type' => 'boolean',
|
||||
'default' => false,
|
||||
),
|
||||
),
|
||||
'render_callback' => 'render_block_core_archives',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
add_action( 'init', 'register_block_core_archives' );
|
39
src/wp-includes/blocks/block.php
Normal file
39
src/wp-includes/blocks/block.php
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
/**
|
||||
* Server-side rendering of the `core/block` block.
|
||||
*
|
||||
* @package gutenberg
|
||||
*/
|
||||
|
||||
/**
|
||||
* Renders the `core/block` block on server.
|
||||
*
|
||||
* @param array $attributes The block attributes.
|
||||
*
|
||||
* @return string Rendered HTML of the referenced block.
|
||||
*/
|
||||
function render_block_core_block( $attributes ) {
|
||||
if ( empty( $attributes['ref'] ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$reusable_block = get_post( $attributes['ref'] );
|
||||
if ( ! $reusable_block || 'wp_block' !== $reusable_block->post_type ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return do_blocks( $reusable_block->post_content );
|
||||
}
|
||||
|
||||
register_block_type(
|
||||
'core/block',
|
||||
array(
|
||||
'attributes' => array(
|
||||
'ref' => array(
|
||||
'type' => 'number',
|
||||
),
|
||||
),
|
||||
|
||||
'render_callback' => 'render_block_core_block',
|
||||
)
|
||||
);
|
103
src/wp-includes/blocks/categories.php
Normal file
103
src/wp-includes/blocks/categories.php
Normal file
@ -0,0 +1,103 @@
|
||||
<?php
|
||||
/**
|
||||
* Server-side rendering of the `core/categories` block.
|
||||
*
|
||||
* @package gutenberg
|
||||
*/
|
||||
|
||||
/**
|
||||
* Renders the `core/categories` block on server.
|
||||
*
|
||||
* @param array $attributes The block attributes.
|
||||
*
|
||||
* @return string Returns the categories list/dropdown markup.
|
||||
*/
|
||||
function render_block_core_categories( $attributes ) {
|
||||
static $block_id = 0;
|
||||
$block_id++;
|
||||
|
||||
$align = 'center';
|
||||
if ( isset( $attributes['align'] ) && in_array( $attributes['align'], array( 'left', 'right', 'full' ), true ) ) {
|
||||
$align = $attributes['align'];
|
||||
}
|
||||
|
||||
$args = array(
|
||||
'echo' => false,
|
||||
'hierarchical' => ! empty( $attributes['showHierarchy'] ),
|
||||
'orderby' => 'name',
|
||||
'show_count' => ! empty( $attributes['showPostCounts'] ),
|
||||
'title_li' => '',
|
||||
);
|
||||
|
||||
if ( ! empty( $attributes['displayAsDropdown'] ) ) {
|
||||
$id = 'wp-block-categories-' . $block_id;
|
||||
$args['id'] = $id;
|
||||
$args['show_option_none'] = __( 'Select Category', 'gutenberg' );
|
||||
$wrapper_markup = '<div class="%1$s">%2$s</div>';
|
||||
$items_markup = wp_dropdown_categories( $args );
|
||||
$type = 'dropdown';
|
||||
|
||||
if ( ! is_admin() ) {
|
||||
$wrapper_markup .= build_dropdown_script_block_core_categories( $id );
|
||||
}
|
||||
} else {
|
||||
$wrapper_markup = '<ul class="%1$s">%2$s</ul>';
|
||||
$items_markup = wp_list_categories( $args );
|
||||
$type = 'list';
|
||||
}
|
||||
|
||||
$class = "wp-block-categories wp-block-categories-{$type} align{$align}";
|
||||
|
||||
if ( isset( $attributes['className'] ) ) {
|
||||
$class .= ' ' . $attributes['className'];
|
||||
}
|
||||
|
||||
$block_content = sprintf(
|
||||
$wrapper_markup,
|
||||
esc_attr( $class ),
|
||||
$items_markup
|
||||
);
|
||||
|
||||
return $block_content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the inline script for a categories dropdown field.
|
||||
*
|
||||
* @param string $dropdown_id ID of the dropdown field.
|
||||
*
|
||||
* @return string Returns the dropdown onChange redirection script.
|
||||
*/
|
||||
function build_dropdown_script_block_core_categories( $dropdown_id ) {
|
||||
ob_start();
|
||||
?>
|
||||
<script type='text/javascript'>
|
||||
/* <![CDATA[ */
|
||||
(function() {
|
||||
var dropdown = document.getElementById( '<?php echo esc_js( $dropdown_id ); ?>' );
|
||||
function onCatChange() {
|
||||
if ( dropdown.options[ dropdown.selectedIndex ].value > 0 ) {
|
||||
location.href = "<?php echo home_url(); ?>/?cat=" + dropdown.options[ dropdown.selectedIndex ].value;
|
||||
}
|
||||
}
|
||||
dropdown.onchange = onCatChange;
|
||||
})();
|
||||
/* ]]> */
|
||||
</script>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the `core/categories` block on server.
|
||||
*/
|
||||
function register_block_core_categories() {
|
||||
register_block_type(
|
||||
'core/categories',
|
||||
array(
|
||||
'render_callback' => 'render_block_core_categories',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
add_action( 'init', 'register_block_core_categories' );
|
182
src/wp-includes/blocks/latest-comments.php
Normal file
182
src/wp-includes/blocks/latest-comments.php
Normal file
@ -0,0 +1,182 @@
|
||||
<?php
|
||||
/**
|
||||
* Server-side rendering of the `core/latest-comments` block.
|
||||
*
|
||||
* @package gutenberg
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get the post title.
|
||||
*
|
||||
* The post title is fetched and if it is blank then a default string is
|
||||
* returned.
|
||||
*
|
||||
* Copied from `wp-admin/includes/template.php`, but we can't include that
|
||||
* file because:
|
||||
*
|
||||
* 1. It causes bugs with test fixture generation and strange Docker 255 error
|
||||
* codes.
|
||||
* 2. It's in the admin; ideally we *shouldn't* be including files from the
|
||||
* admin for a block's output. It's a very small/simple function as well,
|
||||
* so duplicating it isn't too terrible.
|
||||
*
|
||||
* @since 3.3.0
|
||||
*
|
||||
* @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is global $post.
|
||||
* @return string The post title if set; "(no title)" if no title is set.
|
||||
*/
|
||||
function gutenberg_draft_or_post_title( $post = 0 ) {
|
||||
$title = get_the_title( $post );
|
||||
if ( empty( $title ) ) {
|
||||
$title = __( '(no title)', 'gutenberg' );
|
||||
}
|
||||
return esc_html( $title );
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the `core/latest-comments` block on server.
|
||||
*
|
||||
* @param array $attributes The block attributes.
|
||||
*
|
||||
* @return string Returns the post content with latest comments added.
|
||||
*/
|
||||
function gutenberg_render_block_core_latest_comments( $attributes = array() ) {
|
||||
// This filter is documented in wp-includes/widgets/class-wp-widget-recent-comments.php.
|
||||
$comments = get_comments(
|
||||
apply_filters(
|
||||
'widget_comments_args',
|
||||
array(
|
||||
'number' => $attributes['commentsToShow'],
|
||||
'status' => 'approve',
|
||||
'post_status' => 'publish',
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
$list_items_markup = '';
|
||||
if ( ! empty( $comments ) ) {
|
||||
// Prime the cache for associated posts. This is copied from \WP_Widget_Recent_Comments::widget().
|
||||
$post_ids = array_unique( wp_list_pluck( $comments, 'comment_post_ID' ) );
|
||||
_prime_post_caches( $post_ids, strpos( get_option( 'permalink_structure' ), '%category%' ), false );
|
||||
|
||||
foreach ( $comments as $comment ) {
|
||||
$list_items_markup .= '<li class="wp-block-latest-comments__comment">';
|
||||
if ( $attributes['displayAvatar'] ) {
|
||||
$avatar = get_avatar(
|
||||
$comment,
|
||||
48,
|
||||
'',
|
||||
'',
|
||||
array(
|
||||
'class' => 'wp-block-latest-comments__comment-avatar',
|
||||
)
|
||||
);
|
||||
if ( $avatar ) {
|
||||
$list_items_markup .= $avatar;
|
||||
}
|
||||
}
|
||||
|
||||
$list_items_markup .= '<article>';
|
||||
$list_items_markup .= '<footer class="wp-block-latest-comments__comment-meta">';
|
||||
$author_url = get_comment_author_url( $comment );
|
||||
if ( empty( $author_url ) && ! empty( $comment->user_id ) ) {
|
||||
$author_url = get_author_posts_url( $comment->user_id );
|
||||
}
|
||||
|
||||
$author_markup = '';
|
||||
if ( $author_url ) {
|
||||
$author_markup .= '<a class="wp-block-latest-comments__comment-author" href="' . esc_url( $author_url ) . '">' . get_comment_author( $comment ) . '</a>';
|
||||
} else {
|
||||
$author_markup .= '<span class="wp-block-latest-comments__comment-author">' . get_comment_author( $comment ) . '</span>';
|
||||
}
|
||||
|
||||
// `_draft_or_post_title` calls `esc_html()` so we don't need to wrap that call in
|
||||
// `esc_html`.
|
||||
$post_title = '<a class="wp-block-latest-comments__comment-link" href="' . esc_url( get_comment_link( $comment ) ) . '">' . gutenberg_draft_or_post_title( $comment->comment_post_ID ) . '</a>';
|
||||
|
||||
$list_items_markup .= sprintf(
|
||||
/* translators: 1: author name (inside <a> or <span> tag, based on if they have a URL), 2: post title related to this comment */
|
||||
__( '%1$s on %2$s', 'gutenberg' ),
|
||||
$author_markup,
|
||||
$post_title
|
||||
);
|
||||
|
||||
if ( $attributes['displayDate'] ) {
|
||||
$list_items_markup .= sprintf(
|
||||
'<time datetime="%1$s" class="wp-block-latest-comments__comment-date">%2$s</time>',
|
||||
esc_attr( get_comment_date( 'c', $comment ) ),
|
||||
date_i18n( get_option( 'date_format' ), get_comment_date( 'U', $comment ) )
|
||||
);
|
||||
}
|
||||
$list_items_markup .= '</footer>';
|
||||
if ( $attributes['displayExcerpt'] ) {
|
||||
$list_items_markup .= '<div class="wp-block-latest-comments__comment-excerpt">' . wpautop( get_comment_excerpt( $comment ) ) . '</div>';
|
||||
}
|
||||
$list_items_markup .= '</article></li>';
|
||||
}
|
||||
}
|
||||
|
||||
$class = 'wp-block-latest-comments';
|
||||
if ( $attributes['align'] ) {
|
||||
$class .= " align{$attributes['align']}";
|
||||
}
|
||||
if ( $attributes['displayAvatar'] ) {
|
||||
$class .= ' has-avatars';
|
||||
}
|
||||
if ( $attributes['displayDate'] ) {
|
||||
$class .= ' has-dates';
|
||||
}
|
||||
if ( $attributes['displayExcerpt'] ) {
|
||||
$class .= ' has-excerpts';
|
||||
}
|
||||
if ( empty( $comments ) ) {
|
||||
$class .= ' no-comments';
|
||||
}
|
||||
$classnames = esc_attr( $class );
|
||||
|
||||
$block_content = ! empty( $comments ) ? sprintf(
|
||||
'<ol class="%1$s">%2$s</ol>',
|
||||
$classnames,
|
||||
$list_items_markup
|
||||
) : sprintf(
|
||||
'<div class="%1$s">%2$s</div>',
|
||||
$classnames,
|
||||
__( 'No comments to show.', 'gutenberg' )
|
||||
);
|
||||
|
||||
return $block_content;
|
||||
}
|
||||
|
||||
register_block_type(
|
||||
'core/latest-comments',
|
||||
array(
|
||||
'attributes' => array(
|
||||
'className' => array(
|
||||
'type' => 'string',
|
||||
),
|
||||
'commentsToShow' => array(
|
||||
'type' => 'number',
|
||||
'default' => 5,
|
||||
'minimum' => 1,
|
||||
'maximum' => 100,
|
||||
),
|
||||
'displayAvatar' => array(
|
||||
'type' => 'boolean',
|
||||
'default' => true,
|
||||
),
|
||||
'displayDate' => array(
|
||||
'type' => 'boolean',
|
||||
'default' => true,
|
||||
),
|
||||
'displayExcerpt' => array(
|
||||
'type' => 'boolean',
|
||||
'default' => true,
|
||||
),
|
||||
'align' => array(
|
||||
'type' => 'string',
|
||||
'enum' => array( 'center', 'left', 'right', 'wide', 'full', '' ),
|
||||
),
|
||||
),
|
||||
'render_callback' => 'gutenberg_render_block_core_latest_comments',
|
||||
)
|
||||
);
|
125
src/wp-includes/blocks/latest-posts.php
Normal file
125
src/wp-includes/blocks/latest-posts.php
Normal file
@ -0,0 +1,125 @@
|
||||
<?php
|
||||
/**
|
||||
* Server-side rendering of the `core/latest-posts` block.
|
||||
*
|
||||
* @package gutenberg
|
||||
*/
|
||||
|
||||
/**
|
||||
* Renders the `core/latest-posts` block on server.
|
||||
*
|
||||
* @param array $attributes The block attributes.
|
||||
*
|
||||
* @return string Returns the post content with latest posts added.
|
||||
*/
|
||||
function render_block_core_latest_posts( $attributes ) {
|
||||
$recent_posts = wp_get_recent_posts(
|
||||
array(
|
||||
'numberposts' => $attributes['postsToShow'],
|
||||
'post_status' => 'publish',
|
||||
'order' => $attributes['order'],
|
||||
'orderby' => $attributes['orderBy'],
|
||||
'category' => $attributes['categories'],
|
||||
)
|
||||
);
|
||||
|
||||
$list_items_markup = '';
|
||||
|
||||
foreach ( $recent_posts as $post ) {
|
||||
$post_id = $post['ID'];
|
||||
|
||||
$title = get_the_title( $post_id );
|
||||
if ( ! $title ) {
|
||||
$title = __( '(Untitled)', 'gutenberg' );
|
||||
}
|
||||
$list_items_markup .= sprintf(
|
||||
'<li><a href="%1$s">%2$s</a>',
|
||||
esc_url( get_permalink( $post_id ) ),
|
||||
esc_html( $title )
|
||||
);
|
||||
|
||||
if ( isset( $attributes['displayPostDate'] ) && $attributes['displayPostDate'] ) {
|
||||
$list_items_markup .= sprintf(
|
||||
'<time datetime="%1$s" class="wp-block-latest-posts__post-date">%2$s</time>',
|
||||
esc_attr( get_the_date( 'c', $post_id ) ),
|
||||
esc_html( get_the_date( '', $post_id ) )
|
||||
);
|
||||
}
|
||||
|
||||
$list_items_markup .= "</li>\n";
|
||||
}
|
||||
|
||||
$class = 'wp-block-latest-posts';
|
||||
if ( isset( $attributes['align'] ) ) {
|
||||
$class .= ' align' . $attributes['align'];
|
||||
}
|
||||
|
||||
if ( isset( $attributes['postLayout'] ) && 'grid' === $attributes['postLayout'] ) {
|
||||
$class .= ' is-grid';
|
||||
}
|
||||
|
||||
if ( isset( $attributes['columns'] ) && 'grid' === $attributes['postLayout'] ) {
|
||||
$class .= ' columns-' . $attributes['columns'];
|
||||
}
|
||||
|
||||
if ( isset( $attributes['className'] ) ) {
|
||||
$class .= ' ' . $attributes['className'];
|
||||
}
|
||||
|
||||
$block_content = sprintf(
|
||||
'<ul class="%1$s">%2$s</ul>',
|
||||
esc_attr( $class ),
|
||||
$list_items_markup
|
||||
);
|
||||
|
||||
return $block_content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the `core/latest-posts` block on server.
|
||||
*/
|
||||
function register_block_core_latest_posts() {
|
||||
register_block_type(
|
||||
'core/latest-posts',
|
||||
array(
|
||||
'attributes' => array(
|
||||
'categories' => array(
|
||||
'type' => 'string',
|
||||
),
|
||||
'className' => array(
|
||||
'type' => 'string',
|
||||
),
|
||||
'postsToShow' => array(
|
||||
'type' => 'number',
|
||||
'default' => 5,
|
||||
),
|
||||
'displayPostDate' => array(
|
||||
'type' => 'boolean',
|
||||
'default' => false,
|
||||
),
|
||||
'postLayout' => array(
|
||||
'type' => 'string',
|
||||
'default' => 'list',
|
||||
),
|
||||
'columns' => array(
|
||||
'type' => 'number',
|
||||
'default' => 3,
|
||||
),
|
||||
'align' => array(
|
||||
'type' => 'string',
|
||||
),
|
||||
'order' => array(
|
||||
'type' => 'string',
|
||||
'default' => 'desc',
|
||||
),
|
||||
'orderBy' => array(
|
||||
'type' => 'string',
|
||||
'default' => 'date',
|
||||
),
|
||||
),
|
||||
'render_callback' => 'render_block_core_latest_posts',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
add_action( 'init', 'register_block_core_latest_posts' );
|
32
src/wp-includes/blocks/shortcode.php
Normal file
32
src/wp-includes/blocks/shortcode.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
/**
|
||||
* Server-side rendering of the `core/shortcode` block.
|
||||
*
|
||||
* @package gutenberg
|
||||
*/
|
||||
|
||||
/**
|
||||
* Performs wpautop() on the shortcode block content.
|
||||
*
|
||||
* @param array $attributes The block attributes.
|
||||
* @param string $content The block content.
|
||||
*
|
||||
* @return string Returns the block content.
|
||||
*/
|
||||
function render_block_core_shortcode( $attributes, $content ) {
|
||||
return wpautop( $content );
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the `core/shortcode` block on server.
|
||||
*/
|
||||
function register_block_core_shortcode() {
|
||||
register_block_type(
|
||||
'core/shortcode',
|
||||
array(
|
||||
'render_callback' => 'render_block_core_shortcode',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
add_action( 'init', 'register_block_core_shortcode' );
|
@ -310,9 +310,16 @@ class WP_Block_Parser {
|
||||
* otherwise we're nested and we have to close out the current
|
||||
* block and add it as a new innerBlock to the parent
|
||||
*/
|
||||
$stack_top = array_pop( $this->stack );
|
||||
$stack_top->block->innerHTML .= substr( $this->document, $stack_top->prev_offset, $start_offset - $stack_top->prev_offset );
|
||||
$stack_top->prev_offset = $start_offset + $token_length;
|
||||
$stack_top = array_pop( $this->stack );
|
||||
|
||||
$html = substr( $this->document, $stack_top->prev_offset, $start_offset - $stack_top->prev_offset );
|
||||
if ( $stack_top->block->innerBlocks ) {
|
||||
$stack_top->block->innerBlocks[] = (array) $this->freeform( $html );
|
||||
} else {
|
||||
$stack_top->block->innerHTML = $html;
|
||||
}
|
||||
|
||||
$stack_top->prev_offset = $start_offset + $token_length;
|
||||
|
||||
$this->add_inner_block(
|
||||
$stack_top->block,
|
||||
@ -445,8 +452,8 @@ class WP_Block_Parser {
|
||||
*/
|
||||
function add_inner_block( WP_Block_Parser_Block $block, $token_start, $token_length, $last_offset = null ) {
|
||||
$parent = $this->stack[ count( $this->stack ) - 1 ];
|
||||
$parent->block->innerBlocks[] = $block;
|
||||
$parent->block->innerHTML .= substr( $this->document, $parent->prev_offset, $token_start - $parent->prev_offset );
|
||||
$parent->block->innerBlocks[] = (array) $this->freeform( substr( $this->document, $parent->prev_offset, $token_start - $parent->prev_offset ) );
|
||||
$parent->block->innerBlocks[] = (array) $block;
|
||||
$parent->prev_offset = $last_offset ? $last_offset : $token_start + $token_length;
|
||||
}
|
||||
|
||||
@ -461,10 +468,16 @@ class WP_Block_Parser {
|
||||
$stack_top = array_pop( $this->stack );
|
||||
$prev_offset = $stack_top->prev_offset;
|
||||
|
||||
$stack_top->block->innerHTML .= isset( $end_offset )
|
||||
$html = isset( $end_offset )
|
||||
? substr( $this->document, $prev_offset, $end_offset - $prev_offset )
|
||||
: substr( $this->document, $prev_offset );
|
||||
|
||||
if ( $stack_top->block->innerBlocks ) {
|
||||
$stack_top->block->innerBlocks[] = (array) $this->freeform( $html );
|
||||
} else {
|
||||
$stack_top->block->innerHTML = $html;
|
||||
}
|
||||
|
||||
if ( isset( $stack_top->leading_html_start ) ) {
|
||||
$this->output[] = (array) self::freeform(
|
||||
substr(
|
||||
|
@ -181,6 +181,7 @@ add_filter( 'the_title', 'wptexturize' );
|
||||
add_filter( 'the_title', 'convert_chars' );
|
||||
add_filter( 'the_title', 'trim' );
|
||||
|
||||
add_filter( 'the_content', 'do_blocks', 9 );
|
||||
add_filter( 'the_content', 'wptexturize' );
|
||||
add_filter( 'the_content', 'convert_smilies', 20 );
|
||||
add_filter( 'the_content', 'wpautop' );
|
||||
|
@ -458,6 +458,11 @@ function wpautop( $pee, $br = true ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// We don't need to autop posts with blocks in them.
|
||||
if ( has_blocks( $pee ) ) {
|
||||
return $pee;
|
||||
}
|
||||
|
||||
// Just to make things a little easier, pad the end.
|
||||
$pee = $pee . "\n";
|
||||
|
||||
@ -3635,6 +3640,7 @@ function wp_trim_excerpt( $text = '' ) {
|
||||
$text = get_the_content( '' );
|
||||
|
||||
$text = strip_shortcodes( $text );
|
||||
$text = strip_dynamic_blocks( $text );
|
||||
|
||||
/** This filter is documented in wp-includes/post-template.php */
|
||||
$text = apply_filters( 'the_content', $text );
|
||||
|
@ -248,6 +248,12 @@ require( ABSPATH . WPINC . '/class-wp-block-type.php' );
|
||||
require( ABSPATH . WPINC . '/class-wp-block-type-registry.php' );
|
||||
require( ABSPATH . WPINC . '/class-wp-block-parser.php' );
|
||||
require( ABSPATH . WPINC . '/blocks.php' );
|
||||
require( ABSPATH . WPINC . '/blocks/archives.php' );
|
||||
require( ABSPATH . WPINC . '/blocks/block.php' );
|
||||
require( ABSPATH . WPINC . '/blocks/categories.php' );
|
||||
require( ABSPATH . WPINC . '/blocks/latest-comments.php' );
|
||||
require( ABSPATH . WPINC . '/blocks/latest-posts.php' );
|
||||
require( ABSPATH . WPINC . '/blocks/shortcode.php' );
|
||||
|
||||
$GLOBALS['wp_embed'] = new WP_Embed();
|
||||
|
||||
|
@ -2,13 +2,18 @@
|
||||
|
||||
<!--more-->
|
||||
|
||||
|
||||
<p>First Gutenberg Paragraph</p>
|
||||
|
||||
|
||||
<p>Second Auto Paragraph</p>
|
||||
|
||||
|
||||
|
||||
|
||||
<p>Third Gutenberg Paragraph</p>
|
||||
|
||||
|
||||
<p>Third Auto Paragraph</p>
|
||||
|
||||
<p>[someshortcode]</p>
|
||||
|
@ -0,0 +1 @@
|
||||
|
@ -0,0 +1 @@
|
||||
<div class="wp-block-archives">No archives to show.</div>
|
@ -0,0 +1 @@
|
||||
<div class="wp-block-archives">No archives to show.</div>
|
@ -0,0 +1,5 @@
|
||||
|
||||
<figure class="wp-block-audio alignright">
|
||||
<audio controls="" src="https://media.simplecast.com/episodes/audio/80564/draft-podcast-51-livePublish2.mp3"></audio>
|
||||
</figure>
|
||||
|
@ -0,0 +1 @@
|
||||
|
@ -0,0 +1,3 @@
|
||||
|
||||
<div class="wp-block-button aligncenter"><a class="wp-block-button__link" href="https://github.com/WordPress/gutenberg">Help build Gutenberg</a></div>
|
||||
|
@ -0,0 +1 @@
|
||||
<ul class="wp-block-categories wp-block-categories-list aligncenter"><li class="cat-item-none">No categories</li></ul>
|
@ -0,0 +1,5 @@
|
||||
|
||||
<pre class="wp-block-code"><code>export default function MyButton() {
|
||||
return <Button>Click Me!</Button>;
|
||||
}</code></pre>
|
||||
|
@ -3,20 +3,38 @@
|
||||
"blockName": "core/column",
|
||||
"attrs": {},
|
||||
"innerBlocks": [
|
||||
{
|
||||
"blockName": null,
|
||||
"attrs": {},
|
||||
"innerBlocks": [],
|
||||
"innerHTML": "\n<div class=\"wp-block-column\">\n\t"
|
||||
},
|
||||
{
|
||||
"blockName": "core/paragraph",
|
||||
"attrs": {},
|
||||
"innerBlocks": [],
|
||||
"innerHTML": "\n\t<p>Column One, Paragraph One</p>\n\t"
|
||||
},
|
||||
{
|
||||
"blockName": null,
|
||||
"attrs": {},
|
||||
"innerBlocks": [],
|
||||
"innerHTML": "\n\t"
|
||||
},
|
||||
{
|
||||
"blockName": "core/paragraph",
|
||||
"attrs": {},
|
||||
"innerBlocks": [],
|
||||
"innerHTML": "\n\t<p>Column One, Paragraph Two</p>\n\t"
|
||||
}
|
||||
],
|
||||
"innerHTML": "\n<div class=\"wp-block-column\">\n\t\n\t\n</div>\n"
|
||||
},
|
||||
{
|
||||
"blockName": null,
|
||||
"attrs": {},
|
||||
"innerBlocks": [],
|
||||
"innerHTML": "\n</div>\n"
|
||||
}
|
||||
],
|
||||
"innerHTML": ""
|
||||
},
|
||||
{
|
||||
"blockName": null,
|
||||
|
10
tests/phpunit/data/blocks/fixtures/core__column.server.html
Normal file
10
tests/phpunit/data/blocks/fixtures/core__column.server.html
Normal file
@ -0,0 +1,10 @@
|
||||
|
||||
<div class="wp-block-column">
|
||||
|
||||
<p>Column One, Paragraph One</p>
|
||||
|
||||
|
||||
<p>Column One, Paragraph Two</p>
|
||||
|
||||
</div>
|
||||
|
@ -5,46 +5,100 @@
|
||||
"columns": 3
|
||||
},
|
||||
"innerBlocks": [
|
||||
{
|
||||
"blockName": null,
|
||||
"attrs": {},
|
||||
"innerBlocks": [],
|
||||
"innerHTML": "\n<div class=\"wp-block-columns has-3-columns\">\n\t"
|
||||
},
|
||||
{
|
||||
"blockName": "core/column",
|
||||
"attrs": {},
|
||||
"innerBlocks": [
|
||||
{
|
||||
{
|
||||
"blockName": null,
|
||||
"attrs": {},
|
||||
"innerBlocks": [],
|
||||
"innerHTML": "\n\t<div class=\"wp-block-column\">\n\t\t"
|
||||
},
|
||||
{
|
||||
"blockName": "core/paragraph",
|
||||
"attrs": {},
|
||||
"innerBlocks": [],
|
||||
"innerHTML": "\n\t\t<p>Column One, Paragraph One</p>\n\t\t"
|
||||
},
|
||||
{
|
||||
{
|
||||
"blockName": null,
|
||||
"attrs": {},
|
||||
"innerBlocks": [],
|
||||
"innerHTML": "\n\t\t"
|
||||
},
|
||||
{
|
||||
"blockName": "core/paragraph",
|
||||
"attrs": {},
|
||||
"innerBlocks": [],
|
||||
"innerHTML": "\n\t\t<p>Column One, Paragraph Two</p>\n\t\t"
|
||||
}
|
||||
},
|
||||
{
|
||||
"blockName": null,
|
||||
"attrs": {},
|
||||
"innerBlocks": [],
|
||||
"innerHTML": "\n\t</div>\n\t"
|
||||
}
|
||||
],
|
||||
"innerHTML": "\n\t<div class=\"wp-block-column\">\n\t\t\n\t\t\n\t</div>\n\t"
|
||||
"innerHTML": ""
|
||||
},
|
||||
{
|
||||
"blockName": null,
|
||||
"attrs": {},
|
||||
"innerBlocks": [],
|
||||
"innerHTML": "\n\t"
|
||||
},
|
||||
{
|
||||
"blockName": "core/column",
|
||||
"attrs": {},
|
||||
"innerBlocks": [
|
||||
{
|
||||
"innerBlocks": [
|
||||
{
|
||||
"blockName": null,
|
||||
"attrs": {},
|
||||
"innerBlocks": [],
|
||||
"innerHTML": "\n\t<div class=\"wp-block-column\">\n\t\t"
|
||||
},
|
||||
{
|
||||
"blockName": "core/paragraph",
|
||||
"attrs": {},
|
||||
"innerBlocks": [],
|
||||
"innerHTML": "\n\t\t<p>Column Two, Paragraph One</p>\n\t\t"
|
||||
},
|
||||
{
|
||||
{
|
||||
"blockName": null,
|
||||
"attrs": {},
|
||||
"innerBlocks": [],
|
||||
"innerHTML": "\n\t\t"
|
||||
},
|
||||
{
|
||||
"blockName": "core/paragraph",
|
||||
"attrs": {},
|
||||
"innerBlocks": [],
|
||||
"innerHTML": "\n\t\t<p>Column Three, Paragraph One</p>\n\t\t"
|
||||
}
|
||||
},
|
||||
{
|
||||
"blockName": null,
|
||||
"attrs": {},
|
||||
"innerBlocks": [],
|
||||
"innerHTML": "\n\t</div>\n\t"
|
||||
}
|
||||
],
|
||||
"innerHTML": "\n\t<div class=\"wp-block-column\">\n\t\t\n\t\t\n\t</div>\n\t"
|
||||
}
|
||||
"innerHTML": ""
|
||||
},
|
||||
{
|
||||
"blockName": null,
|
||||
"attrs": {},
|
||||
"innerBlocks": [],
|
||||
"innerHTML": "\n</div>\n"
|
||||
}
|
||||
],
|
||||
"innerHTML": "\n<div class=\"wp-block-columns has-3-columns\">\n\t\n\t\n</div>\n"
|
||||
"innerHTML": ""
|
||||
},
|
||||
{
|
||||
"blockName": null,
|
||||
|
24
tests/phpunit/data/blocks/fixtures/core__columns.server.html
Normal file
24
tests/phpunit/data/blocks/fixtures/core__columns.server.html
Normal file
@ -0,0 +1,24 @@
|
||||
|
||||
<div class="wp-block-columns has-3-columns">
|
||||
|
||||
<div class="wp-block-column">
|
||||
|
||||
<p>Column One, Paragraph One</p>
|
||||
|
||||
|
||||
<p>Column One, Paragraph Two</p>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div class="wp-block-column">
|
||||
|
||||
<p>Column Two, Paragraph One</p>
|
||||
|
||||
|
||||
<p>Column Three, Paragraph One</p>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
@ -0,0 +1,5 @@
|
||||
|
||||
<div class="wp-block-cover-image has-background-dim-40 has-background-dim" style="background-image:url(https://cldup.com/uuUqE_dXzy.jpg)">
|
||||
<p class="wp-block-cover-image-text">Guten Berg!</p>
|
||||
</div>
|
||||
|
@ -0,0 +1,8 @@
|
||||
|
||||
<figure class="wp-block-embed">
|
||||
<div class="wp-block-embed__wrapper">
|
||||
https://example.com/
|
||||
</div>
|
||||
<figcaption>Embedded content from an example URL</figcaption>
|
||||
</figure>
|
||||
|
@ -0,0 +1,3 @@
|
||||
|
||||
<div class="wp-block-file"><a href="http://localhost:8888/wp-content/uploads/2018/05/keycodes.js" target="_blank" rel="noreferrer noopener">6546</a><a href="http://localhost:8888/wp-content/uploads/2018/05/keycodes.js" class="wp-block-file__button" download="6546">Download</a></div>
|
||||
|
@ -0,0 +1,3 @@
|
||||
|
||||
<div class="wp-block-file"><a href="http://localhost:8888/?attachment_id=176">lkjfijwef</a></div>
|
||||
|
@ -0,0 +1,3 @@
|
||||
|
||||
<div class="wp-block-file"><a href="http://localhost:8888/wp-content/uploads/2018/05/keycodes.js" class="wp-block-file__button" download="">Download</a></div>
|
||||
|
@ -0,0 +1,6 @@
|
||||
|
||||
Testing freeform block with some
|
||||
<div class="wp-some-class">
|
||||
HTML <span style="color: red;">content</span>
|
||||
</div>
|
||||
|
@ -0,0 +1,4 @@
|
||||
Testing freeform block with some
|
||||
<div class="wp-some-class">
|
||||
HTML <span style="color: red;">content</span>
|
||||
</div>
|
14
tests/phpunit/data/blocks/fixtures/core__gallery.server.html
Normal file
14
tests/phpunit/data/blocks/fixtures/core__gallery.server.html
Normal file
@ -0,0 +1,14 @@
|
||||
|
||||
<ul class="wp-block-gallery columns-2 is-cropped">
|
||||
<li class="blocks-gallery-item">
|
||||
<figure>
|
||||
<img src="https://cldup.com/uuUqE_dXzy.jpg" alt="title" />
|
||||
</figure>
|
||||
</li>
|
||||
<li class="blocks-gallery-item">
|
||||
<figure>
|
||||
<img src="http://google.com/hi.png" alt="title" />
|
||||
</figure>
|
||||
</li>
|
||||
</ul>
|
||||
|
@ -0,0 +1,14 @@
|
||||
|
||||
<ul class="wp-block-gallery columns-1 is-cropped">
|
||||
<li class="blocks-gallery-item">
|
||||
<figure>
|
||||
<img src="https://cldup.com/uuUqE_dXzy.jpg" alt="title" />
|
||||
</figure>
|
||||
</li>
|
||||
<li class="blocks-gallery-item">
|
||||
<figure>
|
||||
<img src="http://google.com/hi.png" alt="title" />
|
||||
</figure>
|
||||
</li>
|
||||
</ul>
|
||||
|
@ -0,0 +1,3 @@
|
||||
|
||||
<h2>The <em>Inserter</em> Tool</h2>
|
||||
|
@ -0,0 +1,3 @@
|
||||
|
||||
<h2>A picture is worth a thousand words, or so the saying goes</h2>
|
||||
|
@ -0,0 +1,4 @@
|
||||
|
||||
<h1>Some HTML code</h1>
|
||||
<marquee>This text will scroll from right to left</marquee>
|
||||
|
@ -0,0 +1,3 @@
|
||||
|
||||
<figure class="wp-block-image"><img src="https://cldup.com/uuUqE_dXzy.jpg" alt="" /></figure>
|
||||
|
@ -0,0 +1,3 @@
|
||||
|
||||
<figure class="wp-block-image"><a href="http://localhost:8888/?attachment_id=7"><img src="https://cldup.com/uuUqE_dXzy.jpg" alt="" /></a></figure>
|
||||
|
@ -0,0 +1,3 @@
|
||||
|
||||
<div class="wp-block-image"><figure class="aligncenter"><img src="https://cldup.com/YLYhpou2oq.jpg" alt="" /><figcaption>Give it a try. Press the "really wide" button on the image toolbar.</figcaption></figure></div>
|
||||
|
@ -0,0 +1,3 @@
|
||||
|
||||
<figure class="wp-block-image"><a href="https://wordpress.org/"><img src="https://cldup.com/uuUqE_dXzy.jpg" alt="" /></a></figure>
|
||||
|
@ -0,0 +1,3 @@
|
||||
|
||||
<figure class="wp-block-image"><a href="https://cldup.com/uuUqE_dXzy.jpg"><img src="https://cldup.com/uuUqE_dXzy.jpg" alt="" /></a></figure>
|
||||
|
@ -0,0 +1 @@
|
||||
|
@ -0,0 +1 @@
|
||||
|
@ -0,0 +1 @@
|
||||
<div class="wp-block-latest-comments has-avatars has-dates has-excerpts no-comments">No comments to show.</div>
|
@ -0,0 +1 @@
|
||||
<ul class="wp-block-latest-posts"></ul>
|
@ -0,0 +1 @@
|
||||
<ul class="wp-block-latest-posts"></ul>
|
@ -0,0 +1,3 @@
|
||||
|
||||
<ul><li>Text & Headings</li><li>Images & Videos</li><li>Galleries</li><li>Embeds, like YouTube, Tweets, or other WordPress posts.</li><li>Layout blocks, like Buttons, Hero Images, Separators, etc.</li><li>And <em>Lists</em> like this one of course :)</li></ul>
|
||||
|
@ -0,0 +1,6 @@
|
||||
|
||||
<p>Testing missing block with some</p>
|
||||
<div class="wp-some-class">
|
||||
HTML <span style="color: red;">content</span>
|
||||
</div>
|
||||
|
@ -0,0 +1,3 @@
|
||||
|
||||
<!--more-->
|
||||
|
@ -0,0 +1,4 @@
|
||||
|
||||
<!--more Continue Reading-->
|
||||
<!--noteaser-->
|
||||
|
@ -0,0 +1,3 @@
|
||||
|
||||
<!--nextpage-->
|
||||
|
@ -0,0 +1,3 @@
|
||||
|
||||
<p style="text-align:right;">... like this one, which is separate from the above and right aligned.</p>
|
||||
|
@ -0,0 +1,3 @@
|
||||
|
||||
Unwrapped is <em>still</em> valid.
|
||||
|
@ -0,0 +1,3 @@
|
||||
|
||||
<pre class="wp-block-preformatted">Some <em>preformatted</em> text...<br>And more!</pre>
|
||||
|
@ -0,0 +1,7 @@
|
||||
|
||||
<figure class="wp-block-pullquote">
|
||||
<blockquote>
|
||||
<p>Testing pullquote block...</p><cite>...with a caption</cite>
|
||||
</blockquote>
|
||||
</figure>
|
||||
|
@ -0,0 +1,9 @@
|
||||
|
||||
<figure class="wp-block-pullquote">
|
||||
<blockquote>
|
||||
<p>Paragraph <strong>one</strong></p>
|
||||
<p>Paragraph two</p>
|
||||
<cite>by whomever</cite>
|
||||
</blockquote>
|
||||
</figure>
|
||||
|
@ -0,0 +1,3 @@
|
||||
|
||||
<blockquote class="wp-block-quote"><p>The editor will endeavour to create a new page and post building experience that makes writing rich posts effortless, and has “blocks” to make it easy what today might take shortcodes, custom HTML, or “mystery meat” embed discovery.</p><cite>Matt Mullenweg, 2017</cite></blockquote>
|
||||
|
@ -0,0 +1,3 @@
|
||||
|
||||
<blockquote class="wp-block-quote is-style-large"><p>There is no greater agony than bearing an untold story inside you.</p><cite>Maya Angelou</cite></blockquote>
|
||||
|
@ -0,0 +1,3 @@
|
||||
|
||||
<hr class="wp-block-separator" />
|
||||
|
@ -0,0 +1,2 @@
|
||||
<p>[gallery ids="238,338"]</p>
|
||||
|
@ -0,0 +1,3 @@
|
||||
|
||||
<div style="height:100px" aria-hidden="true" class="wp-block-spacer"></div>
|
||||
|
@ -0,0 +1,3 @@
|
||||
|
||||
<p class="wp-block-subhead">This is a <em>subhead</em>.</p>
|
||||
|
@ -0,0 +1,3 @@
|
||||
|
||||
<table class="wp-block-table"><thead><tr><th>Version</th><th>Musician</th><th>Date</th></tr></thead><tbody><tr><td><a href="https://wordpress.org/news/2003/05/wordpress-now-available/">.70</a></td><td>No musician chosen.</td><td>May 27, 2003</td></tr><tr><td><a href="https://wordpress.org/news/2004/01/wordpress-10/">1.0</a></td><td>Miles Davis</td><td>January 3, 2004</td></tr><tr><td>Lots of versions skipped, see <a href="https://codex.wordpress.org/WordPress_Versions">the full list</a></td><td>…</td><td>…</td></tr><tr><td><a href="https://wordpress.org/news/2015/12/clifford/">4.4</a></td><td>Clifford Brown</td><td>December 8, 2015</td></tr><tr><td><a href="https://wordpress.org/news/2016/04/coleman/">4.5</a></td><td>Coleman Hawkins</td><td>April 12, 2016</td></tr><tr><td><a href="https://wordpress.org/news/2016/08/pepper/">4.6</a></td><td>Pepper Adams</td><td>August 16, 2016</td></tr><tr><td><a href="https://wordpress.org/news/2016/12/vaughan/">4.7</a></td><td>Sarah Vaughan</td><td>December 6, 2016</td></tr></tbody></table>
|
||||
|
@ -0,0 +1,10 @@
|
||||
|
||||
<div class="wp-block-text-columns aligncenter columns-2">
|
||||
<div class="wp-block-column">
|
||||
<p>One</p>
|
||||
</div>
|
||||
<div class="wp-block-column">
|
||||
<p>Two</p>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -0,0 +1,3 @@
|
||||
|
||||
<p>This is an old-style text block. Changed to <code>paragraph</code> in #2135.</p>
|
||||
|
@ -0,0 +1,3 @@
|
||||
|
||||
<pre class="wp-block-verse">A <em>verse</em>…<br>And more!</pre>
|
||||
|
@ -0,0 +1,3 @@
|
||||
|
||||
<figure class="wp-block-video"><video controls src="https://awesome-fake.video/file.mp4"></video></figure>
|
||||
|
@ -212,3 +212,17 @@ function _wp_rest_server_class_filter() {
|
||||
// Skip `setcookie` calls in auth_cookie functions due to warning:
|
||||
// Cannot modify header information - headers already sent by ...
|
||||
tests_add_filter( 'send_auth_cookies', '__return_false' );
|
||||
|
||||
/**
|
||||
* After the init action has been run once, trying to re-register block types can cause
|
||||
* _doing_it_wrong warnings. To avoid this, unhook the block registration functions.
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
function _unhook_block_registration() {
|
||||
remove_action( 'init', 'register_block_core_archives' );
|
||||
remove_action( 'init', 'register_block_core_categories' );
|
||||
remove_action( 'init', 'register_block_core_latest_posts' );
|
||||
remove_action( 'init', 'register_block_core_shortcode' );
|
||||
}
|
||||
tests_add_filter( 'init', '_unhook_block_registration', 1000 );
|
||||
|
@ -59,7 +59,7 @@ class WP_Test_Block_Parser extends WP_UnitTestCase {
|
||||
|
||||
foreach ( array( $html_path, $parsed_json_path ) as $filename ) {
|
||||
if ( ! file_exists( $filename ) ) {
|
||||
//throw new Exception( "Missing fixture file: '$filename'" );
|
||||
throw new Exception( "Missing fixture file: '$filename'" );
|
||||
}
|
||||
}
|
||||
|
||||
@ -116,5 +116,4 @@ class WP_Test_Block_Parser extends WP_UnitTestCase {
|
||||
protected function strip_r( $input ) {
|
||||
return str_replace( "\r", '', $input );
|
||||
}
|
||||
|
||||
}
|
||||
|
310
tests/phpunit/tests/blocks/render.php
Normal file
310
tests/phpunit/tests/blocks/render.php
Normal file
@ -0,0 +1,310 @@
|
||||
<?php
|
||||
/**
|
||||
* Block rendering tests.
|
||||
*
|
||||
* @package WordPress
|
||||
* @subpackage Blocks
|
||||
* @since 5.0.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Tests for block rendering functions
|
||||
*
|
||||
* @since 5.0.0
|
||||
*
|
||||
* @group blocks
|
||||
*/
|
||||
class WP_Test_Block_Render extends WP_UnitTestCase {
|
||||
/**
|
||||
* The location of the fixtures to test with.
|
||||
*
|
||||
* @since 5.0.0
|
||||
* @var string
|
||||
*/
|
||||
protected static $fixtures_dir;
|
||||
|
||||
/**
|
||||
* Test block instance number.
|
||||
*
|
||||
* @since 5.0.0
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $test_block_instance_number = 0;
|
||||
|
||||
/**
|
||||
* Tear down after each test.
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
public function tearDown() {
|
||||
parent::tearDown();
|
||||
|
||||
$this->test_block_instance_number = 0;
|
||||
|
||||
$registry = WP_Block_Type_Registry::get_instance();
|
||||
if ( $registry->is_registered( 'core/test' ) ) {
|
||||
$registry->unregister( 'core/test' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 45109
|
||||
*/
|
||||
public function test_do_blocks_removes_comments() {
|
||||
$original_html = file_get_contents( DIR_TESTDATA . '/blocks/do-blocks-original.html' );
|
||||
$expected_html = file_get_contents( DIR_TESTDATA . '/blocks/do-blocks-expected.html' );
|
||||
|
||||
$actual_html = do_blocks( $original_html );
|
||||
|
||||
$this->assertEquals( $expected_html, $actual_html );
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 45109
|
||||
*/
|
||||
public function test_the_content() {
|
||||
add_shortcode( 'someshortcode', array( $this, 'handle_shortcode' ) );
|
||||
|
||||
$classic_content = "Foo\n\n[someshortcode]\n\nBar\n\n[/someshortcode]\n\nBaz";
|
||||
$block_content = "<!-- wp:core/paragraph -->\n<p>Foo</p>\n<!-- /wp:core/paragraph -->\n\n<!-- wp:core/shortcode -->[someshortcode]\n\nBar\n\n[/someshortcode]<!-- /wp:core/shortcode -->\n\n<!-- wp:core/paragraph -->\n<p>Baz</p>\n<!-- /wp:core/paragraph -->";
|
||||
|
||||
$classic_filtered_content = apply_filters( 'the_content', $classic_content );
|
||||
$block_filtered_content = apply_filters( 'the_content', $block_content );
|
||||
|
||||
// Block rendering add some extra blank lines, but we're not worried about them.
|
||||
$block_filtered_content = preg_replace( "/\n{2,}/", "\n", $block_filtered_content );
|
||||
|
||||
$this->assertEquals( $classic_filtered_content, $block_filtered_content );
|
||||
}
|
||||
|
||||
function handle_shortcode( $atts, $content ) {
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 45109
|
||||
*/
|
||||
public function data_do_block_test_filenames() {
|
||||
self::$fixtures_dir = DIR_TESTDATA . '/blocks/fixtures';
|
||||
|
||||
$fixture_filenames = array_merge(
|
||||
glob( self::$fixtures_dir . '/*.json' ),
|
||||
glob( self::$fixtures_dir . '/*.html' )
|
||||
);
|
||||
|
||||
$fixture_filenames = array_values(
|
||||
array_unique(
|
||||
array_map(
|
||||
array( $this, 'clean_fixture_filename' ),
|
||||
$fixture_filenames
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
return array_map(
|
||||
array( $this, 'pass_parser_fixture_filenames' ),
|
||||
$fixture_filenames
|
||||
); }
|
||||
|
||||
/**
|
||||
* @dataProvider data_do_block_test_filenames
|
||||
* @ticket 45109
|
||||
*/
|
||||
public function test_do_block_output( $html_filename, $server_html_filename ) {
|
||||
$html_path = self::$fixtures_dir . '/' . $html_filename;
|
||||
$server_html_path = self::$fixtures_dir . '/' . $server_html_filename;
|
||||
|
||||
foreach ( array( $html_path, $server_html_path ) as $filename ) {
|
||||
if ( ! file_exists( $filename ) ) {
|
||||
throw new Exception( "Missing fixture file: '$filename'" );
|
||||
}
|
||||
}
|
||||
|
||||
$html = do_blocks( self::strip_r( file_get_contents( $html_path ) ) );
|
||||
$expected_html = self::strip_r( file_get_contents( $server_html_path ) );
|
||||
|
||||
$this->assertEquals(
|
||||
$expected_html,
|
||||
$html,
|
||||
"File '$html_path' does not match expected value"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 45109
|
||||
*/
|
||||
public function test_dynamic_block_rendering() {
|
||||
$settings = array(
|
||||
'render_callback' => array(
|
||||
$this,
|
||||
'render_test_block',
|
||||
),
|
||||
);
|
||||
register_block_type( 'core/test', $settings );
|
||||
|
||||
// The duplicated dynamic blocks below are there to ensure that do_blocks() replaces each one-by-one.
|
||||
$post_content =
|
||||
'before' .
|
||||
'<!-- wp:core/test {"value":"b1"} --><!-- /wp:core/test -->' .
|
||||
'<!-- wp:core/test {"value":"b1"} --><!-- /wp:core/test -->' .
|
||||
'between' .
|
||||
'<!-- wp:core/test {"value":"b2"} /-->' .
|
||||
'<!-- wp:core/test {"value":"b2"} /-->' .
|
||||
'after';
|
||||
|
||||
$updated_post_content = do_blocks( $post_content );
|
||||
$this->assertEquals(
|
||||
$updated_post_content,
|
||||
'before' .
|
||||
'1:b1' .
|
||||
'2:b1' .
|
||||
'between' .
|
||||
'3:b2' .
|
||||
'4:b2' .
|
||||
'after'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 45109
|
||||
*/
|
||||
public function test_global_post_persistence() {
|
||||
global $post;
|
||||
|
||||
register_block_type(
|
||||
'core/test',
|
||||
array(
|
||||
'render_callback' => array(
|
||||
$this,
|
||||
'render_test_block_wp_query',
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
$posts = self::factory()->post->create_many( 5 );
|
||||
$post = get_post( end( $posts ) );
|
||||
|
||||
$global_post = $post;
|
||||
do_blocks( '<!-- wp:core/test /-->' );
|
||||
|
||||
$this->assertEquals( $global_post, $post );
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 45109
|
||||
*/
|
||||
public function test_dynamic_block_renders_string() {
|
||||
$settings = array(
|
||||
'render_callback' => array(
|
||||
$this,
|
||||
'render_test_block_numeric',
|
||||
),
|
||||
);
|
||||
|
||||
register_block_type( 'core/test', $settings );
|
||||
$block_type = new WP_Block_Type( 'core/test', $settings );
|
||||
|
||||
$rendered = $block_type->render();
|
||||
|
||||
$this->assertSame( '10', $rendered );
|
||||
$this->assertInternalType( 'string', $rendered );
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to remove relative paths and extension from a filename, leaving just the fixture name.
|
||||
*
|
||||
* @since 5.0.0
|
||||
*
|
||||
* @param string $filename The filename to clean.
|
||||
* @return string The cleaned fixture name.
|
||||
*/
|
||||
protected function clean_fixture_filename( $filename ) {
|
||||
$filename = basename( $filename );
|
||||
$filename = preg_replace( '/\..+$/', '', $filename );
|
||||
return $filename;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to return the filenames needed to test the parser output.
|
||||
*
|
||||
* @since 5.0.0
|
||||
*
|
||||
* @param string $filename The cleaned fixture name.
|
||||
* @return array The input and expected output filenames for that fixture.
|
||||
*/
|
||||
protected function pass_parser_fixture_filenames( $filename ) {
|
||||
return array(
|
||||
"$filename.html",
|
||||
"$filename.server.html",
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to remove '\r' characters from a string.
|
||||
*
|
||||
* @since 5.0.0
|
||||
*
|
||||
* @param string $input The string to remove '\r' from.
|
||||
* @return string The input string, with '\r' characters removed.
|
||||
*/
|
||||
protected function strip_r( $input ) {
|
||||
return str_replace( "\r", '', $input );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test block rendering function.
|
||||
*
|
||||
* @since 5.0.0
|
||||
*
|
||||
* @param array $attributes Block attributes.
|
||||
* @return string Block output.
|
||||
*/
|
||||
public function render_test_block( $attributes ) {
|
||||
$this->test_block_instance_number += 1;
|
||||
return $this->test_block_instance_number . ':' . $attributes['value'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test block rendering function, returning numeric value.
|
||||
*
|
||||
* @since 5.0.0
|
||||
*
|
||||
* @return int Block output.
|
||||
*/
|
||||
public function render_test_block_numeric() {
|
||||
return 10;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test block rendering function, creating a new WP_Query instance.
|
||||
*
|
||||
* @since 5.0.0
|
||||
*
|
||||
* @return string Block output.
|
||||
*/
|
||||
public function render_test_block_wp_query() {
|
||||
$content = '';
|
||||
$recent = new WP_Query(
|
||||
array(
|
||||
'numberposts' => 10,
|
||||
'orderby' => 'ID',
|
||||
'order' => 'DESC',
|
||||
'post_type' => 'post',
|
||||
'post_status' => 'draft, publish, future, pending, private',
|
||||
'suppress_filters' => true,
|
||||
)
|
||||
);
|
||||
|
||||
while ( $recent->have_posts() ) {
|
||||
$recent->the_post();
|
||||
|
||||
$content .= get_the_title();
|
||||
}
|
||||
|
||||
wp_reset_postdata();
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
}
|
@ -117,7 +117,14 @@ module.exports = function( env = { environment: 'production', watch: false } ) {
|
||||
};
|
||||
|
||||
const phpFiles = {
|
||||
'block-serialization-default-parser/parser.php': 'wp-includes/class-wp-block-parser.php',
|
||||
// Parser shouldn't be copied until nested block issues are resolved.
|
||||
// 'block-serialization-default-parser/parser.php': 'wp-includes/class-wp-block-parser.php',
|
||||
'block-library/src/archives/index.php': 'wp-includes/blocks/archives.php',
|
||||
'block-library/src/block/index.php': 'wp-includes/blocks/block.php',
|
||||
'block-library/src/categories/index.php': 'wp-includes/blocks/categories.php',
|
||||
'block-library/src/latest-comments/index.php': 'wp-includes/blocks/latest-comments.php',
|
||||
'block-library/src/latest-posts/index.php': 'wp-includes/blocks/latest-posts.php',
|
||||
'block-library/src/shortcode/index.php': 'wp-includes/blocks/shortcode.php',
|
||||
};
|
||||
|
||||
const externals = {
|
||||
|
Loading…
x
Reference in New Issue
Block a user