Editor: Update the WordPress packages to Gutenberg 17.7RC1.

This brings the latest and greatest from Gutenberg.
The full changelog is available here 
https://github.com/WordPress/gutenberg/releases/tag/v17.7.0-rc.1

Props youknowriad, get_dave.
See #60315.
Built from https://develop.svn.wordpress.org/trunk@57578


git-svn-id: http://core.svn.wordpress.org/trunk@57079 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
youknowriad 2024-02-09 18:22:22 +00:00
parent 336be7695c
commit f7c63b630c
227 changed files with 13322 additions and 10228 deletions

View File

@ -833,10 +833,6 @@ $_old_files = array(
'wp-includes/blocks/heading/editor.min.css',
'wp-includes/blocks/heading/editor-rtl.css',
'wp-includes/blocks/heading/editor-rtl.min.css',
'wp-includes/blocks/post-content/editor.css',
'wp-includes/blocks/post-content/editor.min.css',
'wp-includes/blocks/post-content/editor-rtl.css',
'wp-includes/blocks/post-content/editor-rtl.min.css',
'wp-includes/blocks/query-title/editor.css',
'wp-includes/blocks/query-title/editor.min.css',
'wp-includes/blocks/query-title/editor-rtl.css',

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -47,6 +47,9 @@
"__experimentalDefaultControls": {
"fontSize": true
}
},
"interactivity": {
"clientNavigation": true
}
},
"editorStyle": "wp-block-archives-editor"

View File

@ -54,6 +54,9 @@
"margin": false,
"padding": false
}
},
"interactivity": {
"clientNavigation": true
}
},
"editorStyle": "wp-block-audio-editor",

View File

@ -50,6 +50,9 @@
"text": false,
"background": false,
"__experimentalDuotone": "img"
},
"interactivity": {
"clientNavigation": true
}
},
"selectors": {

View File

@ -46,7 +46,20 @@ function render_block_core_block( $attributes ) {
$content = $wp_embed->run_shortcode( $reusable_block->post_content );
$content = $wp_embed->autoembed( $content );
$has_pattern_overrides = isset( $attributes['overrides'] );
// Back compat, the content attribute was previously named overrides and
// had a slightly different format. For blocks that have not been migrated,
// also convert the format here so that the provided `pattern/overrides`
// context is correct.
if ( isset( $attributes['overrides'] ) && ! isset( $attributes['content'] ) ) {
$migrated_content = array();
foreach ( $attributes['overrides'] as $id => $values ) {
$migrated_content[ $id ] = array(
'values' => $values,
);
}
$attributes['content'] = $migrated_content;
}
$has_pattern_overrides = isset( $attributes['content'] );
/**
* We set the `pattern/overrides` context through the `render_block_context`
@ -55,7 +68,7 @@ function render_block_core_block( $attributes ) {
*/
if ( $has_pattern_overrides ) {
$filter_block_context = static function ( $context ) use ( $attributes ) {
$context['pattern/overrides'] = $attributes['overrides'];
$context['pattern/overrides'] = $attributes['content'];
return $context;
};
add_filter( 'render_block_context', $filter_block_context, 1 );

View File

@ -4,14 +4,14 @@
"name": "core/block",
"title": "Pattern",
"category": "reusable",
"description": "Create and save content to reuse across your site. Update the pattern, and the changes apply everywhere its used.",
"description": "Reuse this design across your site.",
"keywords": [ "reusable" ],
"textdomain": "default",
"attributes": {
"ref": {
"type": "number"
},
"overrides": {
"content": {
"type": "object"
}
},
@ -19,6 +19,9 @@
"customClassName": false,
"html": false,
"inserter": false,
"renaming": false
"renaming": false,
"interactivity": {
"clientNavigation": true
}
}
}

View File

@ -48,6 +48,9 @@
'__experimentalDefaultControls' => array(
'fontSize' => true
)
),
'interactivity' => array(
'clientNavigation' => true
)
),
'editorStyle' => 'wp-block-archives-editor'
@ -113,6 +116,9 @@
'margin' => false,
'padding' => false
)
),
'interactivity' => array(
'clientNavigation' => true
)
),
'editorStyle' => 'wp-block-audio-editor',
@ -174,6 +180,9 @@
'text' => false,
'background' => false,
'__experimentalDuotone' => 'img'
),
'interactivity' => array(
'clientNavigation' => true
)
),
'selectors' => array(
@ -188,7 +197,7 @@
'name' => 'core/block',
'title' => 'Pattern',
'category' => 'reusable',
'description' => 'Create and save content to reuse across your site. Update the pattern, and the changes apply everywhere its used.',
'description' => 'Reuse this design across your site.',
'keywords' => array(
'reusable'
),
@ -197,7 +206,7 @@
'ref' => array(
'type' => 'number'
),
'overrides' => array(
'content' => array(
'type' => 'object'
)
),
@ -205,7 +214,10 @@
'customClassName' => false,
'html' => false,
'inserter' => false,
'renaming' => false
'renaming' => false,
'interactivity' => array(
'clientNavigation' => true
)
)
),
'button' => array(
@ -317,7 +329,9 @@
)
),
'reusable' => false,
'shadow' => true,
'shadow' => array(
'__experimentalSkipSerialization' => true
),
'spacing' => array(
'__experimentalSkipSerialization' => true,
'padding' => array(
@ -341,7 +355,10 @@
'width' => true
)
),
'__experimentalSelector' => '.wp-block-button .wp-block-button__link'
'__experimentalSelector' => '.wp-block-button .wp-block-button__link',
'interactivity' => array(
'clientNavigation' => true
)
),
'styles' => array(
array(
@ -363,6 +380,9 @@
'name' => 'core/buttons',
'title' => 'Buttons',
'category' => 'design',
'allowedBlocks' => array(
'core/button'
),
'description' => 'Prompt visitors to take action with a group of button-style links.',
'keywords' => array(
'link'
@ -405,6 +425,9 @@
'default' => array(
'type' => 'flex'
)
),
'interactivity' => array(
'clientNavigation' => true
)
),
'editorStyle' => 'wp-block-buttons-editor',
@ -455,6 +478,9 @@
'__experimentalDefaultControls' => array(
'fontSize' => true
)
),
'interactivity' => array(
'clientNavigation' => true
)
),
'style' => 'wp-block-calendar'
@ -512,6 +538,9 @@
'__experimentalDefaultControls' => array(
'fontSize' => true
)
),
'interactivity' => array(
'clientNavigation' => true
)
),
'editorStyle' => 'wp-block-categories-editor',
@ -580,6 +609,9 @@
'background' => true,
'text' => true
)
),
'interactivity' => array(
'clientNavigation' => true
)
),
'style' => 'wp-block-code'
@ -633,6 +665,7 @@
'text' => true
)
),
'shadow' => true,
'spacing' => array(
'blockGap' => true,
'padding' => true,
@ -664,7 +697,10 @@
'fontSize' => true
)
),
'layout' => true
'layout' => true,
'interactivity' => array(
'clientNavigation' => true
)
)
),
'columns' => array(
@ -673,6 +709,9 @@
'name' => 'core/columns',
'title' => 'Columns',
'category' => 'design',
'allowedBlocks' => array(
'core/column'
),
'description' => 'Display content in multiple columns, with blocks added to each column.',
'textdomain' => 'default',
'attributes' => array(
@ -764,7 +803,11 @@
'__experimentalDefaultControls' => array(
'fontSize' => true
)
)
),
'interactivity' => array(
'clientNavigation' => true
),
'shadow' => true
),
'editorStyle' => 'wp-block-columns-editor',
'style' => 'wp-block-columns'
@ -823,6 +866,9 @@
'__experimentalDefaultControls' => array(
'fontSize' => true
)
),
'interactivity' => array(
'clientNavigation' => true
)
)
),
@ -929,6 +975,9 @@
'__experimentalDefaultControls' => array(
'fontSize' => true
)
),
'interactivity' => array(
'clientNavigation' => true
)
)
),
@ -982,6 +1031,9 @@
'__experimentalDefaultControls' => array(
'fontSize' => true
)
),
'interactivity' => array(
'clientNavigation' => true
)
)
),
@ -1068,6 +1120,9 @@
'__experimentalDefaultControls' => array(
'fontSize' => true
)
),
'interactivity' => array(
'clientNavigation' => true
)
),
'style' => 'wp-block-comment-template'
@ -1139,6 +1194,11 @@
'parent' => array(
'core/comments'
),
'allowedBlocks' => array(
'core/comments-pagination-previous',
'core/comments-pagination-numbers',
'core/comments-pagination-next'
),
'description' => 'Displays a paginated navigation to next/previous set of comments, when applicable.',
'textdomain' => 'default',
'attributes' => array(
@ -1182,6 +1242,9 @@
'__experimentalDefaultControls' => array(
'fontSize' => true
)
),
'interactivity' => array(
'clientNavigation' => true
)
),
'editorStyle' => 'wp-block-comments-pagination-editor',
@ -1229,6 +1292,9 @@
'__experimentalDefaultControls' => array(
'fontSize' => true
)
),
'interactivity' => array(
'clientNavigation' => true
)
)
),
@ -1268,6 +1334,9 @@
'__experimentalDefaultControls' => array(
'fontSize' => true
)
),
'interactivity' => array(
'clientNavigation' => true
)
)
),
@ -1313,6 +1382,9 @@
'__experimentalDefaultControls' => array(
'fontSize' => true
)
),
'interactivity' => array(
'clientNavigation' => true
)
)
),
@ -1384,6 +1456,9 @@
'__experimentalFontStyle' => true,
'__experimentalFontWeight' => true
)
),
'interactivity' => array(
'clientNavigation' => true
)
)
),
@ -1537,6 +1612,9 @@
),
'layout' => array(
'allowJustification' => false
),
'interactivity' => array(
'clientNavigation' => true
)
),
'editorStyle' => 'wp-block-cover-editor',
@ -1610,6 +1688,9 @@
),
'layout' => array(
'allowEditing' => false
),
'interactivity' => array(
'clientNavigation' => true
)
),
'editorStyle' => 'wp-block-details-editor',
@ -1661,6 +1742,9 @@
'align' => true,
'spacing' => array(
'margin' => true
),
'interactivity' => array(
'clientNavigation' => true
)
),
'editorStyle' => 'wp-block-embed-editor',
@ -1809,6 +1893,9 @@
'__experimentalDefaultControls' => array(
'fontSize' => true
)
),
'interactivity' => array(
'clientNavigation' => true
)
),
'style' => 'wp-block-footnotes'
@ -1840,6 +1927,9 @@
'name' => 'core/gallery',
'title' => 'Gallery',
'category' => 'media',
'allowedBlocks' => array(
'core/image'
),
'description' => 'Display multiple images in a rich gallery.',
'keywords' => array(
'images',
@ -1992,6 +2082,9 @@
'default' => array(
'type' => 'flex'
)
),
'interactivity' => array(
'clientNavigation' => true
)
),
'editorStyle' => 'wp-block-gallery-editor',
@ -2105,6 +2198,9 @@
),
'layout' => array(
'allowSizingOnChildren' => true
),
'interactivity' => array(
'clientNavigation' => true
)
),
'editorStyle' => 'wp-block-group-editor',
@ -2181,7 +2277,10 @@
)
),
'__unstablePasteTextInline' => true,
'__experimentalSlashInserter' => true
'__experimentalSlashInserter' => true,
'interactivity' => array(
'clientNavigation' => true
)
),
'editorStyle' => 'wp-block-heading-editor',
'style' => 'wp-block-heading'
@ -2226,6 +2325,9 @@
'__experimentalDefaultControls' => array(
'fontSize' => true
)
),
'interactivity' => array(
'clientNavigation' => true
)
),
'editorStyle' => 'wp-block-home-link-editor',
@ -2251,7 +2353,10 @@
'supports' => array(
'customClassName' => false,
'className' => false,
'html' => false
'html' => false,
'interactivity' => array(
'clientNavigation' => true
)
),
'editorStyle' => 'wp-block-html-editor'
),
@ -2384,10 +2489,14 @@
'radius' => true,
'width' => true
)
),
'shadow' => array(
'__experimentalSkipSerialization' => true
)
),
'selectors' => array(
'border' => '.wp-block-image img, .wp-block-image .wp-block-image__crop-area, .wp-block-image .components-placeholder',
'shadow' => '.wp-block-image img, .wp-block-image .wp-block-image__crop-area, .wp-block-image .components-placeholder',
'filter' => array(
'duotone' => '.wp-block-image img, .wp-block-image .components-placeholder'
)
@ -2456,6 +2565,9 @@
'__experimentalDefaultControls' => array(
'fontSize' => true
)
),
'interactivity' => array(
'clientNavigation' => true
)
),
'editorStyle' => 'wp-block-latest-comments-editor',
@ -2579,6 +2691,9 @@
'__experimentalDefaultControls' => array(
'fontSize' => true
)
),
'interactivity' => array(
'clientNavigation' => true
)
),
'editorStyle' => 'wp-block-latest-posts-editor',
@ -2619,6 +2734,9 @@
'name' => 'core/list',
'title' => 'List',
'category' => 'text',
'allowedBlocks' => array(
'core/list-item'
),
'description' => 'Create a bulleted or numbered list.',
'keywords' => array(
'bullet list',
@ -2692,7 +2810,10 @@
'__unstablePasteTextInline' => true,
'__experimentalSelector' => 'ol,ul',
'__experimentalOnMerge' => true,
'__experimentalSlashInserter' => true
'__experimentalSlashInserter' => true,
'interactivity' => array(
'clientNavigation' => true
)
),
'editorStyle' => 'wp-block-list-editor',
'style' => 'wp-block-list'
@ -2706,6 +2827,9 @@
'parent' => array(
'core/list'
),
'allowedBlocks' => array(
'core/list'
),
'description' => 'Create a list item.',
'textdomain' => 'default',
'attributes' => array(
@ -2742,6 +2866,9 @@
'__experimentalDefaultControls' => array(
'fontSize' => true
)
),
'interactivity' => array(
'clientNavigation' => true
)
)
),
@ -2790,6 +2917,9 @@
'__experimentalDefaultControls' => array(
'fontSize' => true
)
),
'interactivity' => array(
'clientNavigation' => true
)
)
),
@ -2924,6 +3054,9 @@
'__experimentalDefaultControls' => array(
'fontSize' => true
)
),
'interactivity' => array(
'clientNavigation' => true
)
),
'editorStyle' => 'wp-block-media-text-editor',
@ -2954,7 +3087,10 @@
'customClassName' => false,
'inserter' => false,
'html' => false,
'reusable' => false
'reusable' => false,
'interactivity' => array(
'clientNavigation' => true
)
)
),
'more' => array(
@ -2981,7 +3117,10 @@
'customClassName' => false,
'className' => false,
'html' => false,
'multiple' => false
'multiple' => false,
'interactivity' => array(
'clientNavigation' => true
)
),
'editorStyle' => 'wp-block-more-editor'
),
@ -2991,6 +3130,19 @@
'name' => 'core/navigation',
'title' => 'Navigation',
'category' => 'theme',
'allowedBlocks' => array(
'core/navigation-link',
'core/search',
'core/social-links',
'core/page-list',
'core/spacer',
'core/home-link',
'core/site-title',
'core/site-logo',
'core/navigation-submenu',
'core/loginout',
'core/buttons'
),
'description' => 'A collection of blocks that allow visitors to get around your site.',
'keywords' => array(
'menu',
@ -3158,6 +3310,11 @@
'parent' => array(
'core/navigation'
),
'allowedBlocks' => array(
'core/navigation-link',
'core/navigation-submenu',
'core/page-list'
),
'description' => 'Add a page, link, or another item to your navigation.',
'textdomain' => 'default',
'attributes' => array(
@ -3225,7 +3382,10 @@
'fontSize' => true
)
),
'renaming' => false
'renaming' => false,
'interactivity' => array(
'clientNavigation' => true
)
),
'editorStyle' => 'wp-block-navigation-link-editor',
'style' => 'wp-block-navigation-link'
@ -3292,7 +3452,10 @@
),
'supports' => array(
'reusable' => false,
'html' => false
'html' => false,
'interactivity' => array(
'clientNavigation' => true
)
),
'editorStyle' => 'wp-block-navigation-submenu-editor',
'style' => 'wp-block-navigation-submenu'
@ -3315,7 +3478,10 @@
'supports' => array(
'customClassName' => false,
'className' => false,
'html' => false
'html' => false,
'interactivity' => array(
'clientNavigation' => true
)
),
'editorStyle' => 'wp-block-nextpage-editor'
),
@ -3325,6 +3491,9 @@
'name' => 'core/page-list',
'title' => 'Page List',
'category' => 'widgets',
'allowedBlocks' => array(
'core/page-list-item'
),
'description' => 'Display a list of all pages.',
'keywords' => array(
'menu',
@ -3371,6 +3540,9 @@
'__experimentalDefaultControls' => array(
'fontSize' => true
)
),
'interactivity' => array(
'clientNavigation' => true
)
),
'editorStyle' => 'wp-block-page-list-editor',
@ -3429,7 +3601,10 @@
'html' => false,
'lock' => false,
'inserter' => false,
'__experimentalToolbar' => false
'__experimentalToolbar' => false,
'interactivity' => array(
'clientNavigation' => true
)
),
'editorStyle' => 'wp-block-page-list-editor',
'style' => 'wp-block-page-list'
@ -3508,7 +3683,10 @@
)
),
'__experimentalSelector' => 'p',
'__unstablePasteTextInline' => true
'__unstablePasteTextInline' => true,
'interactivity' => array(
'clientNavigation' => true
)
),
'editorStyle' => 'wp-block-paragraph-editor',
'style' => 'wp-block-paragraph'
@ -3523,7 +3701,10 @@
'supports' => array(
'html' => false,
'inserter' => false,
'renaming' => false
'renaming' => false,
'interactivity' => array(
'clientNavigation' => true
)
),
'textdomain' => 'default',
'attributes' => array(
@ -3599,6 +3780,9 @@
'background' => true,
'text' => true
)
),
'interactivity' => array(
'clientNavigation' => true
)
),
'style' => 'wp-block-post-author'
@ -3645,6 +3829,9 @@
'__experimentalDefaultControls' => array(
'fontSize' => true
)
),
'interactivity' => array(
'clientNavigation' => true
)
)
),
@ -3700,6 +3887,9 @@
'__experimentalDefaultControls' => array(
'fontSize' => true
)
),
'interactivity' => array(
'clientNavigation' => true
)
)
),
@ -3860,6 +4050,9 @@
'__experimentalDefaultControls' => array(
'fontSize' => true
)
),
'interactivity' => array(
'clientNavigation' => true
)
)
),
@ -3919,6 +4112,9 @@
'__experimentalDefaultControls' => array(
'fontSize' => true
)
),
'interactivity' => array(
'clientNavigation' => true
)
),
'editorStyle' => 'wp-block-post-excerpt-editor',
@ -4017,6 +4213,9 @@
'spacing' => array(
'margin' => true,
'padding' => true
),
'interactivity' => array(
'clientNavigation' => true
)
),
'editorStyle' => 'wp-block-post-featured-image-editor',
@ -4053,9 +4252,6 @@
'type' => 'string',
'default' => 'none'
),
'inSameTerm' => array(
'type' => 'boolean'
),
'taxonomy' => array(
'type' => 'string',
'default' => ''
@ -4083,6 +4279,9 @@
'__experimentalDefaultControls' => array(
'fontSize' => true
)
),
'interactivity' => array(
'clientNavigation' => true
)
),
'style' => 'wp-block-post-navigation-link'
@ -4142,6 +4341,9 @@
'__experimentalDefaultControls' => array(
'blockGap' => true
)
),
'interactivity' => array(
'clientNavigation' => true
)
),
'style' => 'wp-block-post-template',
@ -4206,6 +4408,9 @@
'__experimentalDefaultControls' => array(
'fontSize' => true
)
),
'interactivity' => array(
'clientNavigation' => true
)
),
'style' => 'wp-block-post-terms'
@ -4276,6 +4481,9 @@
'__experimentalDefaultControls' => array(
'fontSize' => true
)
),
'interactivity' => array(
'clientNavigation' => true
)
),
'style' => 'wp-block-post-title'
@ -4322,6 +4530,9 @@
'__experimentalDefaultControls' => array(
'fontSize' => true
)
),
'interactivity' => array(
'clientNavigation' => true
)
),
'style' => 'wp-block-preformatted'
@ -4402,6 +4613,9 @@
'fontSize' => '1.5em',
'lineHeight' => '1.6'
)
),
'interactivity' => array(
'clientNavigation' => true
)
),
'editorStyle' => 'wp-block-pullquote-editor',
@ -4465,10 +4679,10 @@
'full'
),
'html' => false,
'layout' => true
'layout' => true,
'interactivity' => true
),
'editorStyle' => 'wp-block-query-editor',
'style' => 'wp-block-query'
'editorStyle' => 'wp-block-query-editor'
),
'query-no-results' => array(
'$schema' => 'https://schemas.wp.org/trunk/block.json',
@ -4505,6 +4719,9 @@
'__experimentalDefaultControls' => array(
'fontSize' => true
)
),
'interactivity' => array(
'clientNavigation' => true
)
)
),
@ -4514,9 +4731,14 @@
'name' => 'core/query-pagination',
'title' => 'Pagination',
'category' => 'theme',
'parent' => array(
'ancestor' => array(
'core/query'
),
'allowedBlocks' => array(
'core/query-pagination-previous',
'core/query-pagination-numbers',
'core/query-pagination-next'
),
'description' => 'Displays a paginated navigation to next/previous set of posts, when applicable.',
'textdomain' => 'default',
'attributes' => array(
@ -4569,6 +4791,9 @@
'__experimentalDefaultControls' => array(
'fontSize' => true
)
),
'interactivity' => array(
'clientNavigation' => true
)
),
'editorStyle' => 'wp-block-query-pagination-editor',
@ -4619,6 +4844,9 @@
'__experimentalDefaultControls' => array(
'fontSize' => true
)
),
'interactivity' => array(
'clientNavigation' => true
)
)
),
@ -4666,6 +4894,9 @@
'__experimentalDefaultControls' => array(
'fontSize' => true
)
),
'interactivity' => array(
'clientNavigation' => true
)
),
'editorStyle' => 'wp-block-query-pagination-numbers-editor'
@ -4715,6 +4946,9 @@
'__experimentalDefaultControls' => array(
'fontSize' => true
)
),
'interactivity' => array(
'clientNavigation' => true
)
)
),
@ -4775,6 +5009,9 @@
'__experimentalDefaultControls' => array(
'fontSize' => true
)
),
'interactivity' => array(
'clientNavigation' => true
)
),
'style' => 'wp-block-query-title'
@ -4842,6 +5079,9 @@
),
'spacing' => array(
'blockGap' => true
),
'interactivity' => array(
'clientNavigation' => true
)
),
'styles' => array(
@ -4915,6 +5155,9 @@
'__experimentalDefaultControls' => array(
'width' => true
)
),
'interactivity' => array(
'clientNavigation' => true
)
),
'style' => 'wp-block-read-more'
@ -4967,7 +5210,10 @@
),
'supports' => array(
'align' => true,
'html' => false
'html' => false,
'interactivity' => array(
'clientNavigation' => true
)
),
'editorStyle' => 'wp-block-rss-editor',
'style' => 'wp-block-rss'
@ -5113,6 +5359,9 @@
'top',
'bottom'
)
),
'interactivity' => array(
'clientNavigation' => true
)
),
'styles' => array(
@ -5201,6 +5450,9 @@
'margin' => false,
'padding' => false
)
),
'interactivity' => array(
'clientNavigation' => true
)
),
'styles' => array(
@ -5269,6 +5521,9 @@
'__experimentalDefaultControls' => array(
'fontSize' => true
)
),
'interactivity' => array(
'clientNavigation' => true
)
),
'editorStyle' => 'wp-block-site-tagline-editor'
@ -5336,6 +5591,9 @@
'__experimentalDefaultControls' => array(
'fontSize' => true
)
),
'interactivity' => array(
'clientNavigation' => true
)
),
'editorStyle' => 'wp-block-site-title-editor',
@ -5376,7 +5634,10 @@
),
'supports' => array(
'reusable' => false,
'html' => false
'html' => false,
'interactivity' => array(
'clientNavigation' => true
)
),
'editorStyle' => 'wp-block-social-link-editor'
),
@ -5386,6 +5647,9 @@
'name' => 'core/social-links',
'title' => 'Social Icons',
'category' => 'widgets',
'allowedBlocks' => array(
'core/social-link'
),
'description' => 'Display icons linking to your social media profiles or sites.',
'keywords' => array(
'links'
@ -5474,6 +5738,9 @@
'margin' => true,
'padding' => false
)
),
'interactivity' => array(
'clientNavigation' => true
)
),
'styles' => array(
@ -5524,6 +5791,9 @@
'__experimentalDefaultControls' => array(
'margin' => true
)
),
'interactivity' => array(
'clientNavigation' => true
)
),
'editorStyle' => 'wp-block-spacer-editor',
@ -5738,7 +6008,10 @@
'width' => true
)
),
'__experimentalSelector' => '.wp-block-table > table'
'__experimentalSelector' => '.wp-block-table > table',
'interactivity' => array(
'clientNavigation' => true
)
),
'styles' => array(
array(
@ -5811,6 +6084,9 @@
'__experimentalFontStyle' => true,
'__experimentalTextTransform' => true,
'__experimentalLetterSpacing' => true
),
'interactivity' => array(
'clientNavigation' => true
)
),
'editorStyle' => 'wp-block-tag-cloud-editor'
@ -5841,7 +6117,10 @@
'align' => true,
'html' => false,
'reusable' => false,
'renaming' => false
'renaming' => false,
'interactivity' => array(
'clientNavigation' => true
)
),
'editorStyle' => 'wp-block-template-part-editor'
),
@ -5887,6 +6166,9 @@
'__experimentalDefaultControls' => array(
'fontSize' => true
)
),
'interactivity' => array(
'clientNavigation' => true
)
)
),
@ -5928,7 +6210,10 @@
)
),
'supports' => array(
'inserter' => false
'inserter' => false,
'interactivity' => array(
'clientNavigation' => true
)
),
'editorStyle' => 'wp-block-text-columns-editor',
'style' => 'wp-block-text-columns'
@ -5993,6 +6278,9 @@
'width' => true,
'color' => true,
'style' => true
),
'interactivity' => array(
'clientNavigation' => true
)
),
'style' => 'wp-block-verse',
@ -6092,6 +6380,9 @@
'margin' => false,
'padding' => false
)
),
'interactivity' => array(
'clientNavigation' => true
)
),
'editorStyle' => 'wp-block-video-editor',

View File

@ -98,7 +98,9 @@
}
},
"reusable": false,
"shadow": true,
"shadow": {
"__experimentalSkipSerialization": true
},
"spacing": {
"__experimentalSkipSerialization": true,
"padding": [ "horizontal", "vertical" ],
@ -119,7 +121,10 @@
"width": true
}
},
"__experimentalSelector": ".wp-block-button .wp-block-button__link"
"__experimentalSelector": ".wp-block-button .wp-block-button__link",
"interactivity": {
"clientNavigation": true
}
},
"styles": [
{ "name": "fill", "label": "Fill", "isDefault": true },

View File

@ -4,6 +4,7 @@
"name": "core/buttons",
"title": "Buttons",
"category": "design",
"allowedBlocks": [ "core/button" ],
"description": "Prompt visitors to take action with a group of button-style links.",
"keywords": [ "link" ],
"textdomain": "default",
@ -38,6 +39,9 @@
"default": {
"type": "flex"
}
},
"interactivity": {
"clientNavigation": true
}
},
"editorStyle": "wp-block-buttons-editor",

View File

@ -37,6 +37,9 @@
"__experimentalDefaultControls": {
"fontSize": true
}
},
"interactivity": {
"clientNavigation": true
}
},
"style": "wp-block-calendar"

View File

@ -51,6 +51,9 @@
"__experimentalDefaultControls": {
"fontSize": true
}
},
"interactivity": {
"clientNavigation": true
}
},
"editorStyle": "wp-block-categories-editor",

View File

@ -56,6 +56,9 @@
"background": true,
"text": true
}
},
"interactivity": {
"clientNavigation": true
}
},
"style": "wp-block-code"

View File

@ -37,6 +37,7 @@
"text": true
}
},
"shadow": true,
"spacing": {
"blockGap": true,
"padding": true,
@ -68,6 +69,9 @@
"fontSize": true
}
},
"layout": true
"layout": true,
"interactivity": {
"clientNavigation": true
}
}
}

View File

@ -4,6 +4,7 @@
"name": "core/columns",
"title": "Columns",
"category": "design",
"allowedBlocks": [ "core/column" ],
"description": "Display content in multiple columns, with blocks added to each column.",
"textdomain": "default",
"attributes": {
@ -78,7 +79,11 @@
"__experimentalDefaultControls": {
"fontSize": true
}
}
},
"interactivity": {
"clientNavigation": true
},
"shadow": true
},
"editorStyle": "wp-block-columns-editor",
"style": "wp-block-columns"

View File

@ -48,6 +48,9 @@
"__experimentalDefaultControls": {
"fontSize": true
}
},
"interactivity": {
"clientNavigation": true
}
}
}

View File

@ -44,6 +44,9 @@
"__experimentalDefaultControls": {
"fontSize": true
}
},
"interactivity": {
"clientNavigation": true
}
}
}

View File

@ -44,6 +44,9 @@
"__experimentalDefaultControls": {
"fontSize": true
}
},
"interactivity": {
"clientNavigation": true
}
}
}

View File

@ -28,6 +28,9 @@
"__experimentalDefaultControls": {
"fontSize": true
}
},
"interactivity": {
"clientNavigation": true
}
},
"style": "wp-block-comment-template"

View File

@ -35,6 +35,9 @@
"__experimentalDefaultControls": {
"fontSize": true
}
},
"interactivity": {
"clientNavigation": true
}
}
}

View File

@ -30,6 +30,9 @@
"__experimentalDefaultControls": {
"fontSize": true
}
},
"interactivity": {
"clientNavigation": true
}
}
}

View File

@ -35,6 +35,9 @@
"__experimentalDefaultControls": {
"fontSize": true
}
},
"interactivity": {
"clientNavigation": true
}
}
}

View File

@ -5,6 +5,11 @@
"title": "Comments Pagination",
"category": "theme",
"parent": [ "core/comments" ],
"allowedBlocks": [
"core/comments-pagination-previous",
"core/comments-pagination-numbers",
"core/comments-pagination-next"
],
"description": "Displays a paginated navigation to next/previous set of comments, when applicable.",
"textdomain": "default",
"attributes": {
@ -48,6 +53,9 @@
"__experimentalDefaultControls": {
"fontSize": true
}
},
"interactivity": {
"clientNavigation": true
}
},
"editorStyle": "wp-block-comments-pagination-editor",

View File

@ -61,6 +61,9 @@
"__experimentalFontStyle": true,
"__experimentalFontWeight": true
}
},
"interactivity": {
"clientNavigation": true
}
}
}

View File

@ -132,6 +132,9 @@
},
"layout": {
"allowJustification": false
},
"interactivity": {
"clientNavigation": true
}
},
"editorStyle": "wp-block-cover-editor",

View File

@ -58,6 +58,9 @@
},
"layout": {
"allowEditing": false
},
"interactivity": {
"clientNavigation": true
}
},
"editorStyle": "wp-block-details-editor",

View File

@ -44,6 +44,9 @@
"align": true,
"spacing": {
"margin": true
},
"interactivity": {
"clientNavigation": true
}
},
"editorStyle": "wp-block-embed-editor",

View File

@ -10,9 +10,13 @@
.wp-block-embed .components-placeholder__error{
word-break:break-word;
}
.wp-block-embed .components-placeholder__learn-more{
.wp-block-embed__learn-more{
margin-top:1em;
}
.wp-block-post-content .wp-block-embed__learn-more a{
color:var(--wp-admin-theme-color);
}
.block-library-embed__interactive-overlay{
bottom:0;

View File

@ -1 +1 @@
.wp-block-embed{clear:both;margin-left:0;margin-right:0}.wp-block-embed.is-loading{display:flex;justify-content:center}.wp-block-embed .components-placeholder__error{word-break:break-word}.wp-block-embed .components-placeholder__learn-more{margin-top:1em}.block-library-embed__interactive-overlay{bottom:0;left:0;opacity:0;position:absolute;right:0;top:0}.wp-block[data-align=left]>.wp-block-embed,.wp-block[data-align=right]>.wp-block-embed{max-width:360px;width:100%}.wp-block[data-align=left]>.wp-block-embed .wp-block-embed__wrapper,.wp-block[data-align=right]>.wp-block-embed .wp-block-embed__wrapper{min-width:280px}
.wp-block-embed{clear:both;margin-left:0;margin-right:0}.wp-block-embed.is-loading{display:flex;justify-content:center}.wp-block-embed .components-placeholder__error{word-break:break-word}.wp-block-embed__learn-more{margin-top:1em}.wp-block-post-content .wp-block-embed__learn-more a{color:var(--wp-admin-theme-color)}.block-library-embed__interactive-overlay{bottom:0;left:0;opacity:0;position:absolute;right:0;top:0}.wp-block[data-align=left]>.wp-block-embed,.wp-block[data-align=right]>.wp-block-embed{max-width:360px;width:100%}.wp-block[data-align=left]>.wp-block-embed .wp-block-embed__wrapper,.wp-block[data-align=right]>.wp-block-embed .wp-block-embed__wrapper{min-width:280px}

View File

@ -10,9 +10,13 @@
.wp-block-embed .components-placeholder__error{
word-break:break-word;
}
.wp-block-embed .components-placeholder__learn-more{
.wp-block-embed__learn-more{
margin-top:1em;
}
.wp-block-post-content .wp-block-embed__learn-more a{
color:var(--wp-admin-theme-color);
}
.block-library-embed__interactive-overlay{
bottom:0;

View File

@ -1 +1 @@
.wp-block-embed{clear:both;margin-left:0;margin-right:0}.wp-block-embed.is-loading{display:flex;justify-content:center}.wp-block-embed .components-placeholder__error{word-break:break-word}.wp-block-embed .components-placeholder__learn-more{margin-top:1em}.block-library-embed__interactive-overlay{bottom:0;left:0;opacity:0;position:absolute;right:0;top:0}.wp-block[data-align=left]>.wp-block-embed,.wp-block[data-align=right]>.wp-block-embed{max-width:360px;width:100%}.wp-block[data-align=left]>.wp-block-embed .wp-block-embed__wrapper,.wp-block[data-align=right]>.wp-block-embed .wp-block-embed__wrapper{min-width:280px}
.wp-block-embed{clear:both;margin-left:0;margin-right:0}.wp-block-embed.is-loading{display:flex;justify-content:center}.wp-block-embed .components-placeholder__error{word-break:break-word}.wp-block-embed__learn-more{margin-top:1em}.wp-block-post-content .wp-block-embed__learn-more a{color:var(--wp-admin-theme-color)}.block-library-embed__interactive-overlay{bottom:0;left:0;opacity:0;position:absolute;right:0;top:0}.wp-block[data-align=left]>.wp-block-embed,.wp-block[data-align=right]>.wp-block-embed{max-width:360px;width:100%}.wp-block[data-align=left]>.wp-block-embed .wp-block-embed__wrapper,.wp-block[data-align=right]>.wp-block-embed .wp-block-embed__wrapper{min-width:280px}

View File

@ -38,6 +38,17 @@ function render_block_core_file( $attributes, $content ) {
// If it's interactive, enqueue the script module and add the directives.
if ( ! empty( $attributes['displayPreview'] ) ) {
$suffix = wp_scripts_get_suffix();
if ( defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN ) {
$module_url = gutenberg_url( '/build/interactivity/file.min.js' );
}
wp_register_script_module(
'@wordpress/block-library/file',
isset( $module_url ) ? $module_url : includes_url( "blocks/file/view{$suffix}.js" ),
array( '@wordpress/interactivity' ),
defined( 'GUTENBERG_VERSION' ) ? GUTENBERG_VERSION : get_bloginfo( 'version' )
);
wp_enqueue_script_module( '@wordpress/block-library/file' );
$processor = new WP_HTML_Tag_Processor( $content );
@ -62,12 +73,5 @@ function register_block_core_file() {
'render_callback' => 'render_block_core_file',
)
);
wp_register_script_module(
'@wordpress/block-library/file',
defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN ? gutenberg_url( '/build/interactivity/file.min.js' ) : includes_url( 'blocks/file/view.min.js' ),
array( '@wordpress/interactivity' ),
defined( 'GUTENBERG_VERSION' ) ? GUTENBERG_VERSION : get_bloginfo( 'version' )
);
}
add_action( 'init', 'register_block_core_file' );

View File

@ -89,5 +89,7 @@ const createActiveXObject = type => {
return browserSupportsPdfs();
}
}
}, {
lock: true
});

View File

@ -1 +1 @@
import*as e from"@wordpress/interactivity";var t={d:(e,o)=>{for(var r in o)t.o(o,r)&&!t.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:o[r]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)};const o=(e=>{var o={};return t.d(o,e),o})({store:()=>e.store}),r=e=>{let t;try{t=new window.ActiveXObject(e)}catch(e){t=void 0}return t};(0,o.store)("core/file",{state:{get hasPdfPreview(){return!(window.navigator.userAgent.indexOf("Mobi")>-1||window.navigator.userAgent.indexOf("Android")>-1||window.navigator.userAgent.indexOf("Macintosh")>-1&&window.navigator.maxTouchPoints&&window.navigator.maxTouchPoints>2||(window.ActiveXObject||"ActiveXObject"in window)&&!r("AcroPDF.PDF")&&!r("PDF.PdfCtrl"))}}});
import*as e from"@wordpress/interactivity";var t={d:(e,o)=>{for(var r in o)t.o(o,r)&&!t.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:o[r]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)};const o=(e=>{var o={};return t.d(o,e),o})({store:()=>e.store}),r=e=>{let t;try{t=new window.ActiveXObject(e)}catch(e){t=void 0}return t};(0,o.store)("core/file",{state:{get hasPdfPreview(){return!(window.navigator.userAgent.indexOf("Mobi")>-1||window.navigator.userAgent.indexOf("Android")>-1||window.navigator.userAgent.indexOf("Macintosh")>-1&&window.navigator.maxTouchPoints&&window.navigator.maxTouchPoints>2||(window.ActiveXObject||"ActiveXObject"in window)&&!r("AcroPDF.PDF")&&!r("PDF.PdfCtrl"))}}},{lock:!0});

View File

@ -55,6 +55,9 @@
"__experimentalDefaultControls": {
"fontSize": true
}
},
"interactivity": {
"clientNavigation": true
}
},
"style": "wp-block-footnotes"

View File

@ -33,32 +33,18 @@ function block_core_gallery_data_id_backcompatibility( $parsed_block ) {
add_filter( 'render_block_data', 'block_core_gallery_data_id_backcompatibility' );
/**
* Filter to randomize the order of image blocks.
*
* @param array $parsed_block The block being rendered.
* @return array The block object with randomized order of image blocks.
*/
function block_core_gallery_random_order( $parsed_block ) {
if ( 'core/gallery' === $parsed_block['blockName'] && ! empty( $parsed_block['attrs']['randomOrder'] ) ) {
shuffle( $parsed_block['innerBlocks'] );
}
return $parsed_block;
}
add_filter( 'render_block_data', 'block_core_gallery_random_order' );
/**
* Adds a style tag for the --wp--style--unstable-gallery-gap var.
*
* The Gallery block needs to recalculate Image block width based on
* the current gap setting in order to maintain the number of flex columns
* so a css var is added to allow this.
* Renders the `core/gallery` block on the server.
*
* @param array $attributes Attributes of the block being rendered.
* @param string $content Content of the block being rendered.
* @return string The content of the block being rendered.
*/
function block_core_gallery_render( $attributes, $content ) {
// Adds a style tag for the --wp--style--unstable-gallery-gap var.
// The Gallery block needs to recalculate Image block width based on
// the current gap setting in order to maintain the number of flex columns
// so a css var is added to allow this.
$gap = $attributes['style']['spacing']['blockGap'] ?? null;
// Skip if gap value contains unsupported characters.
// Regex for CSS value borrowed from `safecss_filter_attr`, and used here
@ -130,7 +116,51 @@ function block_core_gallery_render( $attributes, $content ) {
'context' => 'block-supports',
)
);
return (string) $processed_content;
// The WP_HTML_Tag_Processor class calls get_updated_html() internally
// when the instance is treated as a string, but here we explicitly
// convert it to a string.
$updated_content = $processed_content->get_updated_html();
/*
* Randomize the order of image blocks. Ideally we should shuffle
* the `$parsed_block['innerBlocks']` via the `render_block_data` hook.
* However, this hook doesn't apply inner block updates when blocks are
* nested.
* @todo: In the future, if this hook supports updating innerBlocks in
* nested blocks, it should be refactored.
*
* @see: https://github.com/WordPress/gutenberg/pull/58733
*/
if ( empty( $attributes['randomOrder'] ) ) {
return $updated_content;
}
// This pattern matches figure elements with the `wp-block-image` class to
// avoid the gallery's wrapping `figure` element and extract images only.
$pattern = '/<figure[^>]*\bwp-block-image\b[^>]*>.*?<\/figure>/';
// Find all Image blocks.
preg_match_all( $pattern, $updated_content, $matches );
if ( ! $matches ) {
return $updated_content;
}
$image_blocks = $matches[0];
// Randomize the order of Image blocks.
shuffle( $image_blocks );
$i = 0;
$content = preg_replace_callback(
$pattern,
static function () use ( $image_blocks, &$i ) {
$new_image_block = $image_blocks[ $i ];
++$i;
return $new_image_block;
},
$updated_content
);
return $content;
}
/**
* Registers the `core/gallery` block on server.

View File

@ -4,6 +4,7 @@
"name": "core/gallery",
"title": "Gallery",
"category": "media",
"allowedBlocks": [ "core/image" ],
"description": "Display multiple images in a rich gallery.",
"keywords": [ "images", "photos" ],
"textdomain": "default",
@ -136,6 +137,9 @@
"default": {
"type": "flex"
}
},
"interactivity": {
"clientNavigation": true
}
},
"editorStyle": "wp-block-gallery-editor",

View File

@ -87,6 +87,9 @@
},
"layout": {
"allowSizingOnChildren": true
},
"interactivity": {
"clientNavigation": true
}
},
"editorStyle": "wp-block-group-editor",

View File

@ -61,7 +61,10 @@
}
},
"__unstablePasteTextInline": true,
"__experimentalSlashInserter": true
"__experimentalSlashInserter": true,
"interactivity": {
"clientNavigation": true
}
},
"editorStyle": "wp-block-heading-editor",
"style": "wp-block-heading"

View File

@ -129,7 +129,10 @@ function block_core_home_link_build_li_wrapper_attributes( $context ) {
*/
function render_block_core_home_link( $attributes, $content, $block ) {
if ( empty( $attributes['label'] ) ) {
return '';
// Using a fallback for the label attribute allows rendering the block even if no attributes have been set,
// e.g. when using the block as a hooked block.
// Note that the fallback value needs to be kept in sync with the one set in `edit.js` (upon first loading the block in the editor).
$attributes['label'] = __( 'Home' );
}
$aria_current = '';

View File

@ -36,6 +36,9 @@
"__experimentalDefaultControls": {
"fontSize": true
}
},
"interactivity": {
"clientNavigation": true
}
},
"editorStyle": "wp-block-home-link-editor",

View File

@ -16,7 +16,10 @@
"supports": {
"customClassName": false,
"className": false,
"html": false
"html": false,
"interactivity": {
"clientNavigation": true
}
},
"editorStyle": "wp-block-html-editor"
}

View File

@ -20,26 +20,26 @@ function render_block_core_image( $attributes, $content, $block ) {
return '';
}
$processor = new WP_HTML_Tag_Processor( $content );
$p = new WP_HTML_Tag_Processor( $content );
if ( ! $processor->next_tag( 'img' ) || null === $processor->get_attribute( 'src' ) ) {
if ( ! $p->next_tag( 'img' ) || null === $p->get_attribute( 'src' ) ) {
return '';
}
if ( isset( $attributes['data-id'] ) ) {
// Add the data-id="$id" attribute to the img element
// to provide backwards compatibility for the Gallery Block,
// which now wraps Image Blocks within innerBlocks.
// The data-id attribute is added in a core/gallery `render_block_data` hook.
$processor->set_attribute( 'data-id', $attributes['data-id'] );
// Adds the data-id="$id" attribute to the img element to provide backwards
// compatibility for the Gallery Block, which now wraps Image Blocks within
// innerBlocks. The data-id attribute is added in a core/gallery
// `render_block_data` hook.
$p->set_attribute( 'data-id', $attributes['data-id'] );
}
$link_destination = isset( $attributes['linkDestination'] ) ? $attributes['linkDestination'] : 'none';
$lightbox_settings = block_core_image_get_lightbox_settings( $block->parsed_block );
/*
* If the lightbox is enabled and the image is not linked, add the filter
* and the JavaScript view file.
* If the lightbox is enabled and the image is not linked, adds the filter and
* the JavaScript view file.
*/
if (
isset( $lightbox_settings ) &&
@ -47,15 +47,27 @@ function render_block_core_image( $attributes, $content, $block ) {
isset( $lightbox_settings['enabled'] ) &&
true === $lightbox_settings['enabled']
) {
$suffix = wp_scripts_get_suffix();
if ( defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN ) {
$module_url = gutenberg_url( '/build/interactivity/image.min.js' );
}
wp_register_script_module(
'@wordpress/block-library/image',
isset( $module_url ) ? $module_url : includes_url( "blocks/image/view{$suffix}.js" ),
array( '@wordpress/interactivity' ),
defined( 'GUTENBERG_VERSION' ) ? GUTENBERG_VERSION : get_bloginfo( 'version' )
);
wp_enqueue_script_module( '@wordpress/block-library/image' );
/*
* This render needs to happen in a filter with priority 15 to ensure that
* it runs after the duotone filter and that duotone styles are applied to
* the image in the lightbox. Lightbox has to work with any plugins that
* might use filters as well. Removing this can be considered in the
* future if the way the blocks are rendered changes, or if a
* new kind of filter is introduced.
* might use filters as well. Removing this can be considered in the future
* if the way the blocks are rendered changes, or if a new kind of filter is
* introduced.
*/
add_filter( 'render_block_core/image', 'block_core_image_render_lightbox', 15, 2 );
} else {
@ -65,7 +77,7 @@ function render_block_core_image( $attributes, $content, $block ) {
remove_filter( 'render_block_core/image', 'block_core_image_render_lightbox', 15 );
}
return $processor->get_updated_html();
return $p->get_updated_html();
}
/**
@ -78,7 +90,7 @@ function render_block_core_image( $attributes, $content, $block ) {
* @return array Filtered block data.
*/
function block_core_image_get_lightbox_settings( $block ) {
// Get the lightbox setting from the block attributes.
// Gets the lightbox setting from the block attributes.
if ( isset( $block['attrs']['lightbox'] ) ) {
$lightbox_settings = $block['attrs']['lightbox'];
}
@ -89,9 +101,9 @@ function block_core_image_get_lightbox_settings( $block ) {
// If not present in global settings, check the top-level global settings.
//
// NOTE: If no block-level settings are found, the previous call to
// `wp_get_global_settings` will return the whole `theme.json`
// structure in which case we can check if the "lightbox" key is present at
// the top-level of the global settings and use its value.
// `wp_get_global_settings` will return the whole `theme.json` structure in
// which case we can check if the "lightbox" key is present at the top-level
// of the global settings and use its value.
if ( isset( $lightbox_settings['lightbox'] ) ) {
$lightbox_settings = wp_get_global_settings( array( 'lightbox' ) );
}
@ -110,103 +122,76 @@ function block_core_image_get_lightbox_settings( $block ) {
*/
function block_core_image_render_lightbox( $block_content, $block ) {
/*
* If it's not possible that an IMG element exists then return the given
* block content as-is. It may be that there's no actual image in the block
* or it could be that another plugin already modified this HTML.
* If there's no IMG tag in the block then return the given block content
* as-is. There's nothing that this code can knowingly modify to add the
* lightbox behavior.
*/
if ( false === stripos( $block_content, '<img' ) ) {
$p = new WP_HTML_Tag_Processor( $block_content );
if ( $p->next_tag( 'figure' ) ) {
$p->set_bookmark( 'figure' );
}
if ( ! $p->next_tag( 'img' ) ) {
return $block_content;
}
$processor = new WP_HTML_Tag_Processor( $block_content );
$alt = $p->get_attribute( 'alt' );
$img_uploaded_src = $p->get_attribute( 'src' );
$img_class_names = $p->get_attribute( 'class' );
$img_styles = $p->get_attribute( 'style' );
$img_width = 'none';
$img_height = 'none';
$aria_label = __( 'Enlarge image' );
$aria_label = __( 'Enlarge image' );
/*
* If there's definitely no IMG element in the block then return the given
* block content as-is. There's nothing that this code can knowingly modify
* to add the lightbox behavior.
*/
if ( ! $processor->next_tag( 'img' ) ) {
return $block_content;
}
$alt_attribute = $processor->get_attribute( 'alt' );
// An empty alt attribute `alt=""` is valid for decorative images.
if ( is_string( $alt_attribute ) ) {
$alt_attribute = trim( $alt_attribute );
}
// It only makes sense to append the alt text to the button aria-label when the alt text is non-empty.
if ( $alt_attribute ) {
if ( $alt ) {
/* translators: %s: Image alt text. */
$aria_label = sprintf( __( 'Enlarge image: %s' ), $alt_attribute );
$aria_label = sprintf( __( 'Enlarge image: %s' ), $alt );
}
// Currently, we are only enabling the zoom animation.
$lightbox_animation = 'zoom';
// Note: We want to store the `src` in the context so we
// can set it dynamically when the lightbox is opened.
if ( isset( $block['attrs']['id'] ) ) {
$img_uploaded_src = wp_get_attachment_url( $block['attrs']['id'] );
$img_metadata = wp_get_attachment_metadata( $block['attrs']['id'] );
$img_width = $img_metadata['width'] ?? 'none';
$img_height = $img_metadata['height'] ?? 'none';
} else {
$img_uploaded_src = $processor->get_attribute( 'src' );
$img_width = 'none';
$img_height = 'none';
}
if ( isset( $block['attrs']['scale'] ) ) {
$scale_attr = $block['attrs']['scale'];
} else {
$scale_attr = false;
}
$w = new WP_HTML_Tag_Processor( $block_content );
$w->next_tag( 'figure' );
$w->add_class( 'wp-lightbox-container' );
$w->set_attribute( 'data-wp-interactive', '{"namespace":"core/image"}' );
$w->set_attribute(
// Figure.
$p->seek( 'figure' );
$figure_class_names = $p->get_attribute( 'class' );
$figure_styles = $p->get_attribute( 'style' );
$p->add_class( 'wp-lightbox-container' );
$p->set_attribute( 'data-wp-interactive', '{"namespace":"core/image"}' );
$p->set_attribute(
'data-wp-context',
sprintf(
'{ "imageLoaded": false,
"initialized": false,
"lightboxEnabled": false,
"hideAnimationEnabled": false,
"preloadInitialized": false,
"lightboxAnimation": "%s",
"imageUploadedSrc": "%s",
"imageCurrentSrc": "",
"targetWidth": "%s",
"targetHeight": "%s",
"scaleAttr": "%s",
"dialogLabel": "%s"
}',
$lightbox_animation,
$img_uploaded_src,
$img_width,
$img_height,
$scale_attr,
__( 'Enlarged image' )
wp_json_encode(
array(
'uploadedSrc' => $img_uploaded_src,
'figureClassNames' => $figure_class_names,
'figureStyles' => $figure_styles,
'imgClassNames' => $img_class_names,
'imgStyles' => $img_styles,
'targetWidth' => $img_width,
'targetHeight' => $img_height,
'scaleAttr' => $block['attrs']['scale'] ?? false,
'ariaLabel' => $aria_label,
'alt' => $alt,
),
JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP
)
);
$w->next_tag( 'img' );
$w->set_attribute( 'data-wp-init', 'callbacks.initOriginImage' );
$w->set_attribute( 'data-wp-on--load', 'actions.handleLoad' );
$w->set_attribute( 'data-wp-watch', 'callbacks.setButtonStyles' );
// We need to set an event callback on the `img` specifically
// because the `figure` element can also contain a caption, and
// we don't want to trigger the lightbox when the caption is clicked.
$w->set_attribute( 'data-wp-on--click', 'actions.showLightbox' );
$w->set_attribute( 'data-wp-watch--setStylesOnResize', 'callbacks.setStylesOnResize' );
$body_content = $w->get_updated_html();
// Add a button alongside image in the body content.
// Image.
$p->next_tag( 'img' );
$p->set_attribute( 'data-wp-init', 'callbacks.setButtonStyles' );
$p->set_attribute( 'data-wp-on--load', 'callbacks.setButtonStyles' );
$p->set_attribute( 'data-wp-on-window--resize', 'callbacks.setButtonStyles' );
// Sets an event callback on the `img` because the `figure` element can also
// contain a caption, and we don't want to trigger the lightbox when the
// caption is clicked.
$p->set_attribute( 'data-wp-on--click', 'actions.showLightbox' );
$body_content = $p->get_updated_html();
// Adds a button alongside image in the body content.
$img = null;
preg_match( '/<img[^>]+>/', $body_content, $img );
@ -229,46 +214,17 @@ function block_core_image_render_lightbox( $block_content, $block ) {
$body_content = preg_replace( '/<img[^>]+>/', $button, $body_content );
// We need both a responsive image and an enlarged image to animate
// the zoom seamlessly on slow internet connections; the responsive
// image is a copy of the one in the body, which animates immediately
// as the lightbox is opened, while the enlarged one is a full-sized
// version that will likely still be loading as the animation begins.
$m = new WP_HTML_Tag_Processor( $block_content );
$m->next_tag( 'figure' );
$m->add_class( 'responsive-image' );
$m->next_tag( 'img' );
// We want to set the 'src' attribute to an empty string in the responsive image
// because otherwise, as of this writing, the wp_filter_content_tags() function in
// WordPress will automatically add a 'srcset' attribute to the image, which will at
// times cause the incorrectly sized image to be loaded in the lightbox on Firefox.
// Because of this, we bind the 'src' attribute explicitly the current src to reliably
// use the exact same image as in the content when the lightbox is first opened while
// we wait for the larger image to load.
$m->set_attribute( 'src', '' );
$m->set_attribute( 'data-wp-bind--src', 'context.imageCurrentSrc' );
$m->set_attribute( 'data-wp-style--object-fit', 'state.lightboxObjectFit' );
$initial_image_content = $m->get_updated_html();
add_action( 'wp_footer', 'block_core_image_print_lightbox_overlay' );
$q = new WP_HTML_Tag_Processor( $block_content );
$q->next_tag( 'figure' );
$q->add_class( 'enlarged-image' );
$q->next_tag( 'img' );
return $body_content;
}
// We set the 'src' attribute to an empty string to prevent the browser from loading the image
// on initial page load, then bind the attribute to a selector that returns the full-sized image src when
// the lightbox is opened. We could use 'loading=lazy' in combination with the 'hidden' attribute to
// accomplish the same behavior, but that approach breaks progressive loading of the image in Safari
// and Chrome (see https://github.com/WordPress/gutenberg/pull/52765#issuecomment-1674008151). Until that
// is resolved, manually setting the 'src' seems to be the best solution to load the large image on demand.
$q->set_attribute( 'src', '' );
$q->set_attribute( 'data-wp-bind--src', 'state.enlargedImgSrc' );
$q->set_attribute( 'data-wp-style--object-fit', 'state.lightboxObjectFit' );
$enlarged_image_content = $q->get_updated_html();
function block_core_image_print_lightbox_overlay() {
$close_button_label = esc_attr__( 'Close' );
// If the current theme does NOT have a `theme.json`, or the colors are not defined,
// we need to set the background color & close button color to some default values
// because we can't get them from the Global Styles.
// If the current theme does NOT have a `theme.json`, or the colors are not
// defined, it needs to set the background color & close button color to some
// default values because it can't get them from the Global Styles.
$background_color = '#fff';
$close_button_color = '#000';
if ( wp_theme_has_theme_json() ) {
@ -281,35 +237,43 @@ function block_core_image_render_lightbox( $block_content, $block ) {
}
}
$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="state.roleAttribute"
data-wp-bind--aria-label="state.dialogLabel"
data-wp-class--initialized="context.initialized"
data-wp-class--active="context.lightboxEnabled"
data-wp-class--hideAnimationEnabled="context.hideAnimationEnabled"
data-wp-bind--aria-modal="state.ariaModal"
data-wp-watch="callbacks.initLightbox"
data-wp-on--keydown="actions.handleKeydown"
data-wp-on--touchstart="actions.handleTouchStart"
data-wp-on--touchmove="actions.handleTouchMove"
data-wp-on--touchend="actions.handleTouchEnd"
data-wp-on--click="actions.hideLightbox"
tabindex="-1"
>
<button type="button" aria-label="$close_button_label" style="fill: $close_button_color" class="close-button" data-wp-on--click="actions.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>
echo <<<HTML
<div
class="wp-lightbox-overlay zoom"
data-wp-interactive='{"namespace":"core/image"}'
data-wp-context='{}'
data-wp-bind--role="state.roleAttribute"
data-wp-bind--aria-label="state.currentImage.ariaLabel"
data-wp-bind--aria-modal="state.ariaModal"
data-wp-class--active="state.overlayEnabled"
data-wp-class--show-closing-animation="state.showClosingAnimation"
data-wp-watch="callbacks.setOverlayFocus"
data-wp-on--keydown="actions.handleKeydown"
data-wp-on--touchstart="actions.handleTouchStart"
data-wp-on--touchmove="actions.handleTouchMove"
data-wp-on--touchend="actions.handleTouchEnd"
data-wp-on--click="actions.hideLightbox"
data-wp-on-window--resize="callbacks.setOverlayStyles"
data-wp-on-window--scroll="actions.handleScroll"
tabindex="-1"
>
<button type="button" aria-label="$close_button_label" style="fill: $close_button_color" class="close-button">
<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">
<figure data-wp-bind--class="state.currentImage.figureClassNames" data-wp-bind--style="state.currentImage.figureStyles">
<img data-wp-bind--alt="state.currentImage.alt" data-wp-bind--class="state.currentImage.imgClassNames" data-wp-bind--style="state.imgStyles" data-wp-bind--src="state.currentImage.currentSrc">
</figure>
</div>
<div class="lightbox-image-container">
<figure data-wp-bind--class="state.currentImage.figureClassNames" data-wp-bind--style="state.currentImage.figureStyles">
<img data-wp-bind--alt="state.currentImage.alt" data-wp-bind--class="state.currentImage.imgClassNames" data-wp-bind--style="state.imgStyles" data-wp-bind--src="state.enlargedSrc">
</figure>
</div>
<div class="scrim" style="background-color: $background_color" aria-hidden="true"></div>
<style data-wp-text="state.overlayStyles"></style>
</div>
HTML;
return str_replace( '</figure>', $lightbox_html . '</figure>', $body_content );
}
/**
@ -322,12 +286,5 @@ function register_block_core_image() {
'render_callback' => 'render_block_core_image',
)
);
wp_register_script_module(
'@wordpress/block-library/image',
defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN ? gutenberg_url( '/build/interactivity/image.min.js' ) : includes_url( 'blocks/image/view.min.js' ),
array( '@wordpress/interactivity' ),
defined( 'GUTENBERG_VERSION' ) ? GUTENBERG_VERSION : get_bloginfo( 'version' )
);
}
add_action( 'init', 'register_block_core_image' );

View File

@ -117,10 +117,14 @@
"radius": true,
"width": true
}
},
"shadow": {
"__experimentalSkipSerialization": true
}
},
"selectors": {
"border": ".wp-block-image img, .wp-block-image .wp-block-image__crop-area, .wp-block-image .components-placeholder",
"shadow": ".wp-block-image img, .wp-block-image .wp-block-image__crop-area, .wp-block-image .components-placeholder",
"filter": {
"duotone": ".wp-block-image img, .wp-block-image .components-placeholder"
}

View File

@ -221,10 +221,10 @@
.wp-lightbox-overlay.active img{
animation:turn-on-visibility .35s both;
}
.wp-lightbox-overlay.hideanimationenabled:not(.active){
.wp-lightbox-overlay.show-closing-animation:not(.active){
animation:turn-off-visibility .35s both;
}
.wp-lightbox-overlay.hideanimationenabled:not(.active) img{
.wp-lightbox-overlay.show-closing-animation:not(.active) img{
animation:turn-off-visibility .25s both;
}
@media (prefers-reduced-motion:no-preference){
@ -242,16 +242,16 @@
.wp-lightbox-overlay.zoom.active .scrim{
animation:turn-on-visibility .4s forwards;
}
.wp-lightbox-overlay.zoom.hideanimationenabled:not(.active){
.wp-lightbox-overlay.zoom.show-closing-animation:not(.active){
animation:none;
}
.wp-lightbox-overlay.zoom.hideanimationenabled:not(.active) .lightbox-image-container{
.wp-lightbox-overlay.zoom.show-closing-animation:not(.active) .lightbox-image-container{
animation:lightbox-zoom-out .4s;
}
.wp-lightbox-overlay.zoom.hideanimationenabled:not(.active) .lightbox-image-container img{
.wp-lightbox-overlay.zoom.show-closing-animation:not(.active) .lightbox-image-container img{
animation:none;
}
.wp-lightbox-overlay.zoom.hideanimationenabled:not(.active) .scrim{
.wp-lightbox-overlay.zoom.show-closing-animation:not(.active) .scrim{
animation:turn-off-visibility .4s forwards;
}
}

File diff suppressed because one or more lines are too long

View File

@ -221,10 +221,10 @@
.wp-lightbox-overlay.active img{
animation:turn-on-visibility .35s both;
}
.wp-lightbox-overlay.hideanimationenabled:not(.active){
.wp-lightbox-overlay.show-closing-animation:not(.active){
animation:turn-off-visibility .35s both;
}
.wp-lightbox-overlay.hideanimationenabled:not(.active) img{
.wp-lightbox-overlay.show-closing-animation:not(.active) img{
animation:turn-off-visibility .25s both;
}
@media (prefers-reduced-motion:no-preference){
@ -242,16 +242,16 @@
.wp-lightbox-overlay.zoom.active .scrim{
animation:turn-on-visibility .4s forwards;
}
.wp-lightbox-overlay.zoom.hideanimationenabled:not(.active){
.wp-lightbox-overlay.zoom.show-closing-animation:not(.active){
animation:none;
}
.wp-lightbox-overlay.zoom.hideanimationenabled:not(.active) .lightbox-image-container{
.wp-lightbox-overlay.zoom.show-closing-animation:not(.active) .lightbox-image-container{
animation:lightbox-zoom-out .4s;
}
.wp-lightbox-overlay.zoom.hideanimationenabled:not(.active) .lightbox-image-container img{
.wp-lightbox-overlay.zoom.show-closing-animation:not(.active) .lightbox-image-container img{
animation:none;
}
.wp-lightbox-overlay.zoom.hideanimationenabled:not(.active) .scrim{
.wp-lightbox-overlay.zoom.show-closing-animation:not(.active) .scrim{
animation:turn-off-visibility .4s forwards;
}
}

File diff suppressed because one or more lines are too long

View File

@ -32,242 +32,315 @@ const interactivity_namespaceObject = x({ ["getContext"]: () => __WEBPACK_EXTERN
* WordPress dependencies
*/
const focusableSelectors = ['a[href]', 'area[href]', 'input:not([disabled]):not([type="hidden"]):not([aria-hidden])', 'select:not([disabled]):not([aria-hidden])', 'textarea:not([disabled]):not([aria-hidden])', 'button:not([disabled]):not([aria-hidden])', 'iframe', 'object', 'embed', '[contenteditable]', '[tabindex]:not([tabindex^="-"])'];
/**
* Stores a context-bound scroll handler.
*
* This callback could be defined inline inside of the store
* object but it's created externally to avoid confusion about
* how its logic is called. This logic is not referenced directly
* by the directives in the markup because the scroll event we
* need to listen to is triggered on the window; so by defining it
* outside of the store, we signal that the behavior here is different.
* If we find a compelling reason to move it to the store, feel free.
*
* @type {Function}
*/
let scrollCallback;
/**
* Tracks whether user is touching screen; used to
* differentiate behavior for touch and mouse input.
* Tracks whether user is touching screen; used to differentiate behavior for
* touch and mouse input.
*
* @type {boolean}
*/
let isTouching = false;
/**
* Tracks the last time the screen was touched; used to
* differentiate behavior for touch and mouse input.
* Tracks the last time the screen was touched; used to differentiate behavior
* for touch and mouse input.
*
* @type {number}
*/
let lastTouchTime = 0;
/**
* Lightbox page-scroll handler: prevents scrolling.
* Stores the image reference of the currently opened lightbox.
*
* This handler is added to prevent scrolling behaviors that
* trigger content shift while the lightbox is open.
*
* It would be better to accomplish this through CSS alone, but
* using overflow: hidden is currently the only way to do so, and
* that causes the layout to shift and prevents the zoom animation
* from working in some cases because we're unable to account for
* the layout shift when doing the animation calculations. Instead,
* here we use JavaScript to prevent and reset the scrolling
* behavior. In the future, we may be able to use CSS or overflow: hidden
* instead to not rely on JavaScript, but this seems to be the best approach
* for now that provides the best visual experience.
*
* @param {Object} ctx Context object with the `core/image` namespace.
* @type {HTMLElement}
*/
function handleScroll(ctx) {
// We can't override the scroll behavior on mobile devices
// because doing so breaks the pinch to zoom functionality, and we
// want to allow users to zoom in further on the high-res image.
if (!isTouching && Date.now() - lastTouchTime > 450) {
// We are unable to use event.preventDefault() to prevent scrolling
// because the scroll event can't be canceled, so we reset the position instead.
window.scrollTo(ctx.scrollLeftReset, ctx.scrollTopReset);
}
}
let imageRef;
/**
* Stores the button reference of the currently opened lightbox.
*
* @type {HTMLElement}
*/
let buttonRef;
const {
state,
actions,
callbacks
} = (0,interactivity_namespaceObject.store)('core/image', {
state: {
windowWidth: window.innerWidth,
windowHeight: window.innerHeight,
currentImage: {},
get overlayOpened() {
return state.currentImage.currentSrc;
},
get roleAttribute() {
const ctx = (0,interactivity_namespaceObject.getContext)();
return ctx.lightboxEnabled ? 'dialog' : null;
return state.overlayOpened ? 'dialog' : null;
},
get ariaModal() {
const ctx = (0,interactivity_namespaceObject.getContext)();
return ctx.lightboxEnabled ? 'true' : null;
return state.overlayOpened ? 'true' : null;
},
get dialogLabel() {
const ctx = (0,interactivity_namespaceObject.getContext)();
return ctx.lightboxEnabled ? ctx.dialogLabel : null;
get enlargedSrc() {
return state.currentImage.uploadedSrc || 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=';
},
get lightboxObjectFit() {
const ctx = (0,interactivity_namespaceObject.getContext)();
if (ctx.initialized) {
return 'cover';
}
},
get enlargedImgSrc() {
const ctx = (0,interactivity_namespaceObject.getContext)();
return ctx.initialized ? ctx.imageUploadedSrc : 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=';
get imgStyles() {
return state.overlayOpened && `${state.currentImage.imgStyles?.replace(/;$/, '')}; object-fit:cover;`;
}
},
actions: {
showLightbox(event) {
showLightbox() {
const ctx = (0,interactivity_namespaceObject.getContext)();
// We can't initialize the lightbox until the reference
// image is loaded, otherwise the UX is broken.
if (!ctx.imageLoaded) {
// Bails out if the image has not loaded yet.
if (!ctx.imageRef?.complete) {
return;
}
ctx.initialized = true;
ctx.lastFocusedElement = window.document.activeElement;
ctx.scrollDelta = 0;
ctx.pointerType = event.pointerType;
ctx.lightboxEnabled = true;
setStyles(ctx, ctx.imageRef);
ctx.scrollTopReset = window.pageYOffset || document.documentElement.scrollTop;
// In most cases, this value will be 0, but this is included
// in case a user has created a page with horizontal scrolling.
ctx.scrollLeftReset = window.pageXOffset || document.documentElement.scrollLeft;
// Stores the positons of the scroll to fix it until the overlay is
// closed.
state.scrollTopReset = document.documentElement.scrollTop;
state.scrollLeftReset = document.documentElement.scrollLeft;
// We define and bind the scroll callback here so
// that we can pass the context and as an argument.
// We may be able to change this in the future if we
// define the scroll callback in the store instead, but
// this approach seems to tbe clearest for now.
scrollCallback = handleScroll.bind(null, ctx);
// Moves the information of the expaned image to the state.
ctx.currentSrc = ctx.imageRef.currentSrc;
imageRef = ctx.imageRef;
buttonRef = ctx.buttonRef;
state.currentImage = ctx;
state.overlayEnabled = true;
// We need to add a scroll event listener to the window
// here because we are unable to otherwise access it via
// the Interactivity API directives. If we add a native way
// to access the window, we can remove this.
window.addEventListener('scroll', scrollCallback, false);
// Computes the styles of the overlay for the animation.
callbacks.setOverlayStyles();
},
hideLightbox() {
const ctx = (0,interactivity_namespaceObject.getContext)();
ctx.hideAnimationEnabled = true;
if (ctx.lightboxEnabled) {
// We want to wait until the close animation is completed
// before allowing a user to scroll again. The duration of this
// animation is defined in the styles.scss and depends on if the
// animation is 'zoom' or 'fade', but in any case we should wait
// a few milliseconds longer than the duration, otherwise a user
// may scroll too soon and cause the animation to look sloppy.
if (state.overlayEnabled) {
// Waits until the close animation has completed before allowing a
// user to scroll again. The duration of this animation is defined in
// the `styles.scss` file, but in any case we should wait a few
// milliseconds longer than the duration, otherwise a user may scroll
// too soon and cause the animation to look sloppy.
setTimeout(function () {
window.removeEventListener('scroll', scrollCallback);
// If we don't delay before changing the focus,
// the focus ring will appear on Firefox before
// the image has finished animating, which looks broken.
ctx.lightboxTriggerRef.focus({
// Delays before changing the focus. Otherwise the focus ring will
// appear on Firefox before the image has finished animating, which
// looks broken.
buttonRef.focus({
preventScroll: true
});
// Resets the current image to mark the overlay as closed.
state.currentImage = {};
imageRef = null;
buttonRef = null;
}, 450);
ctx.lightboxEnabled = false;
// Starts the overlay closing animation. The showClosingAnimation
// class is used to avoid showing it on page load.
state.showClosingAnimation = true;
state.overlayEnabled = false;
}
},
handleKeydown(event) {
const ctx = (0,interactivity_namespaceObject.getContext)();
if (ctx.lightboxEnabled) {
if (event.key === 'Tab' || event.keyCode === 9) {
// If shift + tab it change the direction
if (event.shiftKey && window.document.activeElement === ctx.firstFocusableElement) {
event.preventDefault();
ctx.lastFocusableElement.focus();
} else if (!event.shiftKey && window.document.activeElement === ctx.lastFocusableElement) {
event.preventDefault();
ctx.firstFocusableElement.focus();
}
if (state.overlayEnabled) {
// Focuses the close button when the user presses the tab key.
if (event.key === 'Tab') {
event.preventDefault();
const {
ref
} = (0,interactivity_namespaceObject.getElement)();
ref.querySelector('button').focus();
}
if (event.key === 'Escape' || event.keyCode === 27) {
actions.hideLightbox(event);
// Closes the lightbox when the user presses the escape key.
if (event.key === 'Escape') {
actions.hideLightbox();
}
}
},
// This is fired just by lazily loaded
// images on the page, not all images.
handleLoad() {
const ctx = (0,interactivity_namespaceObject.getContext)();
const {
ref
} = (0,interactivity_namespaceObject.getElement)();
ctx.imageLoaded = true;
ctx.imageCurrentSrc = ref.currentSrc;
callbacks.setButtonStyles();
handleTouchMove(event) {
// On mobile devices, prevents triggering the scroll event because
// otherwise the page jumps around when it resets the scroll position.
// This also means that closing the lightbox requires that a user
// perform a simple tap. This may be changed in the future if there is a
// better alternative to override or reset the scroll position during
// swipe actions.
if (state.overlayEnabled) {
event.preventDefault();
}
},
handleTouchStart() {
isTouching = true;
},
handleTouchMove(event) {
const ctx = (0,interactivity_namespaceObject.getContext)();
// On mobile devices, we want to prevent triggering the
// scroll event because otherwise the page jumps around as
// we reset the scroll position. This also means that closing
// the lightbox requires that a user perform a simple tap. This
// may be changed in the future if we find a better alternative
// to override or reset the scroll position during swipe actions.
if (ctx.lightboxEnabled) {
event.preventDefault();
}
},
handleTouchEnd() {
// We need to wait a few milliseconds before resetting
// to ensure that pinch to zoom works consistently
// on mobile devices when the lightbox is open.
// Waits a few milliseconds before resetting to ensure that pinch to
// zoom works consistently on mobile devices when the lightbox is open.
lastTouchTime = Date.now();
isTouching = false;
},
handleScroll() {
// Prevents scrolling behaviors that trigger content shift while the
// lightbox is open. It would be better to accomplish through CSS alone,
// but using overflow: hidden is currently the only way to do so and
// that causes a layout to shift and prevents the zoom animation from
// working in some cases because it's not possible to account for the
// layout shift when doing the animation calculations. Instead, it uses
// JavaScript to prevent and reset the scrolling behavior.
if (state.overlayOpened) {
// Avoids overriding the scroll behavior on mobile devices because
// doing so breaks the pinch to zoom functionality, and users should
// be able to zoom in further on the high-res image.
if (!isTouching && Date.now() - lastTouchTime > 450) {
// It doesn't rely on `event.preventDefault()` to prevent scrolling
// because the scroll event can't be canceled, so it resets the
// position instead.
window.scrollTo(state.scrollLeftReset, state.scrollTopReset);
}
}
}
},
callbacks: {
initOriginImage() {
setOverlayStyles() {
if (!imageRef) return;
let {
naturalWidth,
naturalHeight,
offsetWidth: originalWidth,
offsetHeight: originalHeight
} = imageRef;
let {
x: screenPosX,
y: screenPosY
} = imageRef.getBoundingClientRect();
// Natural ratio of the image clicked to open the lightbox.
const naturalRatio = naturalWidth / naturalHeight;
// Original ratio of the image clicked to open the lightbox.
let originalRatio = originalWidth / originalHeight;
// If it has object-fit: contain, recalculates the original sizes
// and the screen position without the blank spaces.
if (state.currentImage.scaleAttr === 'contain') {
if (naturalRatio > originalRatio) {
const heightWithoutSpace = originalWidth / naturalRatio;
// Recalculates screen position without the top space.
screenPosY += (originalHeight - heightWithoutSpace) / 2;
originalHeight = heightWithoutSpace;
} else {
const widthWithoutSpace = originalHeight * naturalRatio;
// Recalculates screen position without the left space.
screenPosX += (originalWidth - widthWithoutSpace) / 2;
originalWidth = widthWithoutSpace;
}
}
originalRatio = originalWidth / originalHeight;
// Typically, it uses the image's full-sized dimensions. If those
// dimensions have not been set (i.e. an external image with only one
// size), the image's dimensions in the lightbox are the same
// as those of the image in the content.
let imgMaxWidth = parseFloat(state.currentImage.targetWidth !== 'none' ? state.currentImage.targetWidth : naturalWidth);
let imgMaxHeight = parseFloat(state.currentImage.targetHeight !== 'none' ? state.currentImage.targetHeight : naturalHeight);
// Ratio of the biggest image stored in the database.
let imgRatio = imgMaxWidth / imgMaxHeight;
let containerMaxWidth = imgMaxWidth;
let containerMaxHeight = imgMaxHeight;
let containerWidth = imgMaxWidth;
let containerHeight = imgMaxHeight;
// Checks if the target image has a different ratio than the original
// one (thumbnail). Recalculates the width and height.
if (naturalRatio.toFixed(2) !== imgRatio.toFixed(2)) {
if (naturalRatio > imgRatio) {
// If the width is reached before the height, it keeps the maxWidth
// and recalculates the height unless the difference between the
// maxHeight and the reducedHeight is higher than the maxWidth,
// where it keeps the reducedHeight and recalculate the width.
const reducedHeight = imgMaxWidth / naturalRatio;
if (imgMaxHeight - reducedHeight > imgMaxWidth) {
imgMaxHeight = reducedHeight;
imgMaxWidth = reducedHeight * naturalRatio;
} else {
imgMaxHeight = imgMaxWidth / naturalRatio;
}
} else {
// If the height is reached before the width, it keeps the maxHeight
// and recalculate the width unlesss the difference between the
// maxWidth and the reducedWidth is higher than the maxHeight, where
// it keeps the reducedWidth and recalculate the height.
const reducedWidth = imgMaxHeight * naturalRatio;
if (imgMaxWidth - reducedWidth > imgMaxHeight) {
imgMaxWidth = reducedWidth;
imgMaxHeight = reducedWidth / naturalRatio;
} else {
imgMaxWidth = imgMaxHeight * naturalRatio;
}
}
containerWidth = imgMaxWidth;
containerHeight = imgMaxHeight;
imgRatio = imgMaxWidth / imgMaxHeight;
// Calculates the max size of the container.
if (originalRatio > imgRatio) {
containerMaxWidth = imgMaxWidth;
containerMaxHeight = containerMaxWidth / originalRatio;
} else {
containerMaxHeight = imgMaxHeight;
containerMaxWidth = containerMaxHeight * originalRatio;
}
}
// If the image has been pixelated on purpose, it keeps that size.
if (originalWidth > containerWidth || originalHeight > containerHeight) {
containerWidth = originalWidth;
containerHeight = originalHeight;
}
// Calculates the final lightbox image size and the scale factor.
// MaxWidth is either the window container (accounting for padding) or
// the image resolution.
let horizontalPadding = 0;
if (window.innerWidth > 480) {
horizontalPadding = 80;
} else if (window.innerWidth > 1920) {
horizontalPadding = 160;
}
const verticalPadding = 80;
const targetMaxWidth = Math.min(window.innerWidth - horizontalPadding, containerWidth);
const targetMaxHeight = Math.min(window.innerHeight - verticalPadding, containerHeight);
const targetContainerRatio = targetMaxWidth / targetMaxHeight;
if (originalRatio > targetContainerRatio) {
// If targetMaxWidth is reached before targetMaxHeight.
containerWidth = targetMaxWidth;
containerHeight = containerWidth / originalRatio;
} else {
// If targetMaxHeight is reached before targetMaxWidth.
containerHeight = targetMaxHeight;
containerWidth = containerHeight * originalRatio;
}
const containerScale = originalWidth / containerWidth;
const lightboxImgWidth = imgMaxWidth * (containerWidth / containerMaxWidth);
const lightboxImgHeight = imgMaxHeight * (containerHeight / containerMaxHeight);
// As of this writing, using the calculations above will render the
// lightbox with a small, erroneous whitespace on the left side of the
// image in iOS Safari, perhaps due to an inconsistency in how browsers
// handle absolute positioning and CSS transformation. In any case,
// adding 1 pixel to the container width and height solves the problem,
// though this can be removed if the issue is fixed in the future.
state.overlayStyles = `
:root {
--wp--lightbox-initial-top-position: ${screenPosY}px;
--wp--lightbox-initial-left-position: ${screenPosX}px;
--wp--lightbox-container-width: ${containerWidth + 1}px;
--wp--lightbox-container-height: ${containerHeight + 1}px;
--wp--lightbox-image-width: ${lightboxImgWidth}px;
--wp--lightbox-image-height: ${lightboxImgHeight}px;
--wp--lightbox-scale: ${containerScale};
--wp--lightbox-scrollbar-width: ${window.innerWidth - document.documentElement.clientWidth}px;
}
`;
},
setButtonStyles() {
const ctx = (0,interactivity_namespaceObject.getContext)();
const {
ref
} = (0,interactivity_namespaceObject.getElement)();
ctx.imageRef = ref;
if (ref.complete) {
ctx.imageLoaded = true;
ctx.imageCurrentSrc = ref.currentSrc;
}
},
initTriggerButton() {
const ctx = (0,interactivity_namespaceObject.getContext)();
const {
ref
} = (0,interactivity_namespaceObject.getElement)();
ctx.lightboxTriggerRef = ref;
},
initLightbox() {
const ctx = (0,interactivity_namespaceObject.getContext)();
const {
ref
} = (0,interactivity_namespaceObject.getElement)();
if (ctx.lightboxEnabled) {
const focusableElements = ref.querySelectorAll(focusableSelectors);
ctx.firstFocusableElement = focusableElements[0];
ctx.lastFocusableElement = focusableElements[focusableElements.length - 1];
// Move focus to the dialog when opening it.
ref.focus();
}
},
setButtonStyles() {
const {
ref
} = (0,interactivity_namespaceObject.getElement)();
const {
naturalWidth,
naturalHeight,
@ -275,18 +348,17 @@ const {
offsetHeight
} = ref;
// If the image isn't loaded yet, we can't
// calculate where the button should be.
// If the image isn't loaded yet, it can't calculate where the button
// should be.
if (naturalWidth === 0 || naturalHeight === 0) {
return;
}
const figure = ref.parentElement;
const figureWidth = ref.parentElement.clientWidth;
// We need special handling for the height because
// a caption will cause the figure to be taller than
// the image, which means we need to account for that
// when calculating the placement of the button in the
// It needs special handling for the height because a caption will cause
// the figure to be taller than the image, which means it needs to
// account for that when calculating the placement of the button in the
// top right corner of the image.
let figureHeight = ref.parentElement.clientHeight;
const caption = figure.querySelector('figcaption');
@ -298,25 +370,24 @@ const {
}
const buttonOffsetTop = figureHeight - offsetHeight;
const buttonOffsetRight = figureWidth - offsetWidth;
const ctx = (0,interactivity_namespaceObject.getContext)();
// In the case of an image with object-fit: contain, the
// size of the <img> element can be larger than the image itself,
// so we need to calculate where to place the button.
// In the case of an image with object-fit: contain, the size of the
// <img> element can be larger than the image itself, so it needs to
// calculate where to place the button.
if (ctx.scaleAttr === 'contain') {
// Natural ratio of the image.
const naturalRatio = naturalWidth / naturalHeight;
// Offset ratio of the image.
const offsetRatio = offsetWidth / offsetHeight;
if (naturalRatio >= offsetRatio) {
// If it reaches the width first, keep
// the width and compute the height.
// If it reaches the width first, it keeps the width and compute the
// height.
const referenceHeight = offsetWidth / naturalRatio;
ctx.imageButtonTop = (offsetHeight - referenceHeight) / 2 + buttonOffsetTop + 16;
ctx.imageButtonRight = buttonOffsetRight + 16;
} else {
// If it reaches the height first, keep
// the height and compute the width.
// If it reaches the height first, it keeps the height and compute
// the width.
const referenceWidth = offsetHeight * naturalRatio;
ctx.imageButtonTop = buttonOffsetTop + 16;
ctx.imageButtonRight = (offsetWidth - referenceWidth) / 2 + buttonOffsetRight + 16;
@ -326,197 +397,24 @@ const {
ctx.imageButtonRight = buttonOffsetRight + 16;
}
},
setStylesOnResize() {
setOverlayFocus() {
if (state.overlayEnabled) {
// Moves the focus to the dialog when it opens.
const {
ref
} = (0,interactivity_namespaceObject.getElement)();
ref.focus();
}
},
initTriggerButton() {
const ctx = (0,interactivity_namespaceObject.getContext)();
const {
ref
} = (0,interactivity_namespaceObject.getElement)();
if (ctx.lightboxEnabled && (state.windowWidth || state.windowHeight)) {
setStyles(ctx, ref);
}
ctx.buttonRef = ref;
}
}
}, {
lock: true
});
window.addEventListener('resize', debounce(() => {
state.windowWidth = window.innerWidth;
state.windowHeight = window.innerHeight;
}));
/**
* Computes styles for the lightbox and adds them to the document.
*
* @function
* @param {Object} ctx - Context for the `core/image` namespace.
* @param {Object} ref - The element reference.
*/
function setStyles(ctx, ref) {
// The reference img element lies adjacent
// to the event target button in the DOM.
let {
naturalWidth,
naturalHeight,
offsetWidth: originalWidth,
offsetHeight: originalHeight
} = ref;
let {
x: screenPosX,
y: screenPosY
} = ref.getBoundingClientRect();
// Natural ratio of the image clicked to open the lightbox.
const naturalRatio = naturalWidth / naturalHeight;
// Original ratio of the image clicked to open the lightbox.
let originalRatio = originalWidth / originalHeight;
// If it has object-fit: contain, recalculate the original sizes
// and the screen position without the blank spaces.
if (ctx.scaleAttr === 'contain') {
if (naturalRatio > originalRatio) {
const heightWithoutSpace = originalWidth / naturalRatio;
// Recalculate screen position without the top space.
screenPosY += (originalHeight - heightWithoutSpace) / 2;
originalHeight = heightWithoutSpace;
} else {
const widthWithoutSpace = originalHeight * naturalRatio;
// Recalculate screen position without the left space.
screenPosX += (originalWidth - widthWithoutSpace) / 2;
originalWidth = widthWithoutSpace;
}
}
originalRatio = originalWidth / originalHeight;
// Typically, we use the image's full-sized dimensions. If those
// dimensions have not been set (i.e. an external image with only one size),
// the image's dimensions in the lightbox are the same
// as those of the image in the content.
let imgMaxWidth = parseFloat(ctx.targetWidth !== 'none' ? ctx.targetWidth : naturalWidth);
let imgMaxHeight = parseFloat(ctx.targetHeight !== 'none' ? ctx.targetHeight : naturalHeight);
// Ratio of the biggest image stored in the database.
let imgRatio = imgMaxWidth / imgMaxHeight;
let containerMaxWidth = imgMaxWidth;
let containerMaxHeight = imgMaxHeight;
let containerWidth = imgMaxWidth;
let containerHeight = imgMaxHeight;
// Check if the target image has a different ratio than the original one (thumbnail).
// Recalculate the width and height.
if (naturalRatio.toFixed(2) !== imgRatio.toFixed(2)) {
if (naturalRatio > imgRatio) {
// If the width is reached before the height, we keep the maxWidth
// and recalculate the height.
// Unless the difference between the maxHeight and the reducedHeight
// is higher than the maxWidth, where we keep the reducedHeight and
// recalculate the width.
const reducedHeight = imgMaxWidth / naturalRatio;
if (imgMaxHeight - reducedHeight > imgMaxWidth) {
imgMaxHeight = reducedHeight;
imgMaxWidth = reducedHeight * naturalRatio;
} else {
imgMaxHeight = imgMaxWidth / naturalRatio;
}
} else {
// If the height is reached before the width, we keep the maxHeight
// and recalculate the width.
// Unless the difference between the maxWidth and the reducedWidth
// is higher than the maxHeight, where we keep the reducedWidth and
// recalculate the height.
const reducedWidth = imgMaxHeight * naturalRatio;
if (imgMaxWidth - reducedWidth > imgMaxHeight) {
imgMaxWidth = reducedWidth;
imgMaxHeight = reducedWidth / naturalRatio;
} else {
imgMaxWidth = imgMaxHeight * naturalRatio;
}
}
containerWidth = imgMaxWidth;
containerHeight = imgMaxHeight;
imgRatio = imgMaxWidth / imgMaxHeight;
// Calculate the max size of the container.
if (originalRatio > imgRatio) {
containerMaxWidth = imgMaxWidth;
containerMaxHeight = containerMaxWidth / originalRatio;
} else {
containerMaxHeight = imgMaxHeight;
containerMaxWidth = containerMaxHeight * originalRatio;
}
}
// If the image has been pixelated on purpose, keep that size.
if (originalWidth > containerWidth || originalHeight > containerHeight) {
containerWidth = originalWidth;
containerHeight = originalHeight;
}
// Calculate the final lightbox image size and the
// scale factor. MaxWidth is either the window container
// (accounting for padding) or the image resolution.
let horizontalPadding = 0;
if (window.innerWidth > 480) {
horizontalPadding = 80;
} else if (window.innerWidth > 1920) {
horizontalPadding = 160;
}
const verticalPadding = 80;
const targetMaxWidth = Math.min(window.innerWidth - horizontalPadding, containerWidth);
const targetMaxHeight = Math.min(window.innerHeight - verticalPadding, containerHeight);
const targetContainerRatio = targetMaxWidth / targetMaxHeight;
if (originalRatio > targetContainerRatio) {
// If targetMaxWidth is reached before targetMaxHeight
containerWidth = targetMaxWidth;
containerHeight = containerWidth / originalRatio;
} else {
// If targetMaxHeight is reached before targetMaxWidth
containerHeight = targetMaxHeight;
containerWidth = containerHeight * originalRatio;
}
const containerScale = originalWidth / containerWidth;
const lightboxImgWidth = imgMaxWidth * (containerWidth / containerMaxWidth);
const lightboxImgHeight = imgMaxHeight * (containerHeight / containerMaxHeight);
// Add the CSS variables needed.
let styleTag = document.getElementById('wp-lightbox-styles');
if (!styleTag) {
styleTag = document.createElement('style');
styleTag.id = 'wp-lightbox-styles';
document.head.appendChild(styleTag);
}
// As of this writing, using the calculations above will render the lightbox
// with a small, erroneous whitespace on the left side of the image in iOS Safari,
// perhaps due to an inconsistency in how browsers handle absolute positioning and CSS
// transformation. In any case, adding 1 pixel to the container width and height solves
// the problem, though this can be removed if the issue is fixed in the future.
styleTag.innerHTML = `
:root {
--wp--lightbox-initial-top-position: ${screenPosY}px;
--wp--lightbox-initial-left-position: ${screenPosX}px;
--wp--lightbox-container-width: ${containerWidth + 1}px;
--wp--lightbox-container-height: ${containerHeight + 1}px;
--wp--lightbox-image-width: ${lightboxImgWidth}px;
--wp--lightbox-image-height: ${lightboxImgHeight}px;
--wp--lightbox-scale: ${containerScale};
--wp--lightbox-scrollbar-width: ${window.innerWidth - document.documentElement.clientWidth}px;
}
`;
}
/**
* Debounces a function call.
*
* @function
* @param {Function} func - A function to be called
* @param {number} wait - The time to wait before calling the function
*/
function debounce(func, wait = 50) {
let timeout;
return () => {
const later = () => {
timeout = null;
func();
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}

File diff suppressed because one or more lines are too long

View File

@ -46,6 +46,9 @@
"__experimentalDefaultControls": {
"fontSize": true
}
},
"interactivity": {
"clientNavigation": true
}
},
"editorStyle": "wp-block-latest-comments-editor",

View File

@ -110,6 +110,9 @@
"__experimentalDefaultControls": {
"fontSize": true
}
},
"interactivity": {
"clientNavigation": true
}
},
"editorStyle": "wp-block-latest-posts-editor",

View File

@ -5,6 +5,7 @@
"title": "List item",
"category": "text",
"parent": [ "core/list" ],
"allowedBlocks": [ "core/list" ],
"description": "Create a list item.",
"textdomain": "default",
"attributes": {
@ -41,6 +42,9 @@
"__experimentalDefaultControls": {
"fontSize": true
}
},
"interactivity": {
"clientNavigation": true
}
}
}

View File

@ -4,6 +4,7 @@
"name": "core/list",
"title": "List",
"category": "text",
"allowedBlocks": [ "core/list-item" ],
"description": "Create a bulleted or numbered list.",
"keywords": [ "bullet list", "ordered list", "numbered list" ],
"textdomain": "default",
@ -70,7 +71,10 @@
"__unstablePasteTextInline": true,
"__experimentalSelector": "ol,ul",
"__experimentalOnMerge": true,
"__experimentalSlashInserter": true
"__experimentalSlashInserter": true,
"interactivity": {
"clientNavigation": true
}
},
"editorStyle": "wp-block-list-editor",
"style": "wp-block-list"

View File

@ -39,6 +39,9 @@
"__experimentalDefaultControls": {
"fontSize": true
}
},
"interactivity": {
"clientNavigation": true
}
}
}

View File

@ -123,6 +123,9 @@
"__experimentalDefaultControls": {
"fontSize": true
}
},
"interactivity": {
"clientNavigation": true
}
},
"editorStyle": "wp-block-media-text-editor",

View File

@ -23,6 +23,9 @@
"customClassName": false,
"inserter": false,
"html": false,
"reusable": false
"reusable": false,
"interactivity": {
"clientNavigation": true
}
}
}

View File

@ -20,7 +20,10 @@
"customClassName": false,
"className": false,
"html": false,
"multiple": false
"multiple": false,
"interactivity": {
"clientNavigation": true
}
},
"editorStyle": "wp-block-more-editor"
}

View File

@ -132,6 +132,10 @@ function block_core_navigation_link_maybe_urldecode( $url ) {
$query_params = wp_parse_args( $query );
foreach ( $query_params as $query_param ) {
$can_query_param_be_encoded = is_string( $query_param ) && ! empty( $query_param );
if ( ! $can_query_param_be_encoded ) {
continue;
}
if ( rawurldecode( $query_param ) !== $query_param ) {
$is_url_encoded = true;
break;
@ -323,70 +327,40 @@ function build_variation_for_navigation_link( $entity, $kind ) {
}
/**
* Register a variation for a post type / taxonomy for the navigation link block.
* Filters the registered variations for a block type.
* Returns the dynamically built variations for all post-types and taxonomies.
*
* @param array $variation Variation array from build_variation_for_navigation_link.
* @return void
* @since 6.5.0
*
* @param array $variations Array of registered variations for a block type.
* @param WP_Block_Type $block_type The full block type object.
*/
function block_core_navigation_link_register_variation( $variation ) {
// Directly set the variations on the registered block type
// because there's no server side registration for variations (see #47170).
$navigation_block_type = WP_Block_Type_Registry::get_instance()->get_registered( 'core/navigation-link' );
// If the block is not registered yet, bail early.
// Variation will be registered in register_block_core_navigation_link then.
if ( ! $navigation_block_type ) {
return;
function block_core_navigation_link_filter_variations( $variations, $block_type ) {
if ( 'core/navigation-link' !== $block_type->name ) {
return $variations;
}
$navigation_block_type->variations = array_merge(
$navigation_block_type->variations,
array( $variation )
);
$generated_variations = block_core_navigation_link_build_variations();
return array_merge( $variations, $generated_variations );
}
/**
* Unregister a variation for a post type / taxonomy for the navigation link block.
*
* @param string $name Name of the post type / taxonomy (which was used as variation name).
* @return void
*/
function block_core_navigation_link_unregister_variation( $name ) {
// Directly get the variations from the registered block type
// because there's no server side (un)registration for variations (see #47170).
$navigation_block_type = WP_Block_Type_Registry::get_instance()->get_registered( 'core/navigation-link' );
// If the block is not registered (yet), there's no need to remove a variation.
if ( ! $navigation_block_type || empty( $navigation_block_type->variations ) ) {
return;
}
$variations = $navigation_block_type->variations;
// Search for the variation and remove it from the array.
foreach ( $variations as $i => $variation ) {
if ( $variation['name'] === $name ) {
unset( $variations[ $i ] );
break;
}
}
// Reindex array after removing one variation.
$navigation_block_type->variations = array_values( $variations );
}
/**
* Register the navigation link block.
* Returns an array of variations for the navigation link block.
*
* @since 6.5.0
*
* @return array
*/
function build_navigation_link_block_variations() {
// This will only handle post types and taxonomies registered until this point (init on priority 9).
// See action hooks below for other post types and taxonomies.
// See https://github.com/WordPress/gutenberg/issues/53826 for details.
function block_core_navigation_link_build_variations() {
$post_types = get_post_types( array( 'show_in_nav_menus' => true ), 'objects' );
$taxonomies = get_taxonomies( array( 'show_in_nav_menus' => true ), 'objects' );
// Use two separate arrays as a way to order the variations in the UI.
// Known variations (like Post Link and Page Link) are added to the
// `built_ins` array. Variations for custom post types and taxonomies are
// added to the `variations` array and will always appear after `built-ins.
/*
* Use two separate arrays as a way to order the variations in the UI.
* Known variations (like Post Link and Page Link) are added to the
* `built_ins` array. Variations for custom post types and taxonomies are
* added to the `variations` array and will always appear after `built-ins.
*/
$built_ins = array();
$variations = array();
@ -415,76 +389,23 @@ function build_navigation_link_block_variations() {
}
/**
* Register the navigation link block.
* Registers the navigation link block.
*
* @uses render_block_core_navigation()
* @uses render_block_core_navigation_link()
* @uses build_navigation_link_block_variations()
* @throws WP_Error An WP_Error exception parsing the block definition.
*/
function register_block_core_navigation_link() {
register_block_type_from_metadata(
__DIR__ . '/navigation-link',
array(
'render_callback' => 'render_block_core_navigation_link',
'variation_callback' => 'build_navigation_link_block_variations',
'render_callback' => 'render_block_core_navigation_link',
)
);
}
add_action( 'init', 'register_block_core_navigation_link' );
// Register actions for all post types and taxonomies, to add variations when they are registered.
// All post types/taxonomies registered before register_block_core_navigation_link, will be handled by that function.
add_action( 'registered_post_type', 'block_core_navigation_link_register_post_type_variation', 10, 2 );
add_action( 'registered_taxonomy', 'block_core_navigation_link_register_taxonomy_variation', 10, 3 );
// Handle unregistering of post types and taxonomies and remove the variations.
add_action( 'unregistered_post_type', 'block_core_navigation_link_unregister_post_type_variation' );
add_action( 'unregistered_taxonomy', 'block_core_navigation_link_unregister_taxonomy_variation' );
/**
* Register custom post type variations for navigation link on post type registration
* Handles all post types registered after the block is registered in register_navigation_link_post_type_variations
*
* @param string $post_type The post type name passed from registered_post_type action hook.
* @param WP_Post_Type $post_type_object The post type object passed from registered_post_type.
* @return void
* Creates all variations for post types / taxonomies dynamically (= each time when variations are requested).
* Do not use variation_callback, to also account for unregistering post types/taxonomies later on.
*/
function block_core_navigation_link_register_post_type_variation( $post_type, $post_type_object ) {
if ( $post_type_object->show_in_nav_menus ) {
$variation = build_variation_for_navigation_link( $post_type_object, 'post-type' );
block_core_navigation_link_register_variation( $variation );
}
}
/**
* Register a custom taxonomy variation for navigation link on taxonomy registration
* Handles all taxonomies registered after the block is registered in register_navigation_link_post_type_variations
*
* @param string $taxonomy Taxonomy slug.
* @param array|string $object_type Object type or array of object types.
* @param array $args Array of taxonomy registration arguments.
* @return void
*/
function block_core_navigation_link_register_taxonomy_variation( $taxonomy, $object_type, $args ) {
if ( isset( $args['show_in_nav_menus'] ) && $args['show_in_nav_menus'] ) {
$variation = build_variation_for_navigation_link( (object) $args, 'post-type' );
block_core_navigation_link_register_variation( $variation );
}
}
/**
* Unregisters a custom post type variation for navigation link on post type unregistration.
*
* @param string $post_type The post type name passed from unregistered_post_type action hook.
* @return void
*/
function block_core_navigation_link_unregister_post_type_variation( $post_type ) {
block_core_navigation_link_unregister_variation( $post_type );
}
/**
* Unregisters a custom taxonomy variation for navigation link on taxonomy unregistration.
*
* @param string $taxonomy The taxonomy name passed from unregistered_taxonomy action hook.
* @return void
*/
function block_core_navigation_link_unregister_taxonomy_variation( $taxonomy ) {
block_core_navigation_link_unregister_variation( $taxonomy );
}
add_action( 'get_block_type_variations', 'block_core_navigation_link_filter_variations', 10, 2 );

View File

@ -5,6 +5,11 @@
"title": "Custom Link",
"category": "design",
"parent": [ "core/navigation" ],
"allowedBlocks": [
"core/navigation-link",
"core/navigation-submenu",
"core/page-list"
],
"description": "Add a page, link, or another item to your navigation.",
"textdomain": "default",
"attributes": {
@ -72,7 +77,10 @@
"fontSize": true
}
},
"renaming": false
"renaming": false,
"interactivity": {
"clientNavigation": true
}
},
"editorStyle": "wp-block-navigation-link-editor",
"style": "wp-block-navigation-link"

View File

@ -3,4 +3,26 @@
}
.wp-block-navigation .wp-block-navigation-item__description{
display:none;
}
.link-ui-tools{
border-top:1px solid #f0f0f0;
padding:8px;
}
.link-ui-block-inserter{
padding-top:8px;
}
.link-ui-block-inserter__back{
margin-right:8px;
text-transform:uppercase;
}
.components-popover-pointer-events-trap{
background-color:initial;
cursor:pointer;
inset:0;
position:fixed;
z-index:1000000;
}

View File

@ -1 +1 @@
.wp-block-navigation .wp-block-navigation-item__label{overflow-wrap:break-word}.wp-block-navigation .wp-block-navigation-item__description{display:none}
.wp-block-navigation .wp-block-navigation-item__label{overflow-wrap:break-word}.wp-block-navigation .wp-block-navigation-item__description{display:none}.link-ui-tools{border-top:1px solid #f0f0f0;padding:8px}.link-ui-block-inserter{padding-top:8px}.link-ui-block-inserter__back{margin-right:8px;text-transform:uppercase}.components-popover-pointer-events-trap{background-color:initial;cursor:pointer;inset:0;position:fixed;z-index:1000000}

View File

@ -3,4 +3,26 @@
}
.wp-block-navigation .wp-block-navigation-item__description{
display:none;
}
.link-ui-tools{
border-top:1px solid #f0f0f0;
padding:8px;
}
.link-ui-block-inserter{
padding-top:8px;
}
.link-ui-block-inserter__back{
margin-left:8px;
text-transform:uppercase;
}
.components-popover-pointer-events-trap{
background-color:initial;
cursor:pointer;
inset:0;
position:fixed;
z-index:1000000;
}

View File

@ -1 +1 @@
.wp-block-navigation .wp-block-navigation-item__label{overflow-wrap:break-word}.wp-block-navigation .wp-block-navigation-item__description{display:none}
.wp-block-navigation .wp-block-navigation-item__label{overflow-wrap:break-word}.wp-block-navigation .wp-block-navigation-item__description{display:none}.link-ui-tools{border-top:1px solid #f0f0f0;padding:8px}.link-ui-block-inserter{padding-top:8px}.link-ui-block-inserter__back{margin-left:8px;text-transform:uppercase}.components-popover-pointer-events-trap{background-color:initial;cursor:pointer;inset:0;position:fixed;z-index:1000000}

View File

@ -58,7 +58,10 @@
],
"supports": {
"reusable": false,
"html": false
"html": false,
"interactivity": {
"clientNavigation": true
}
},
"editorStyle": "wp-block-navigation-submenu-editor",
"style": "wp-block-navigation-submenu"

View File

@ -9,18 +9,11 @@
* Helper functions used to render the navigation block.
*/
class WP_Navigation_Block_Renderer {
/**
* Used to determine which blocks are wrapped in an <li>.
*
* @var array
* Used to determine whether or not a navigation has submenus.
*/
private static $nav_blocks_wrapped_in_list_item = array(
'core/navigation-link',
'core/home-link',
'core/site-title',
'core/site-logo',
'core/navigation-submenu',
);
private static $has_submenus = false;
/**
* Used to determine which blocks need an <li> wrapper.
@ -58,22 +51,37 @@ class WP_Navigation_Block_Renderer {
* Returns whether or not a navigation has a submenu.
*
* @param WP_Block_List $inner_blocks The list of inner blocks.
* @return bool Returns whether or not a navigation has a submenu.
* @return bool Returns whether or not a navigation has a submenu and also sets the member variable.
*/
private static function has_submenus( $inner_blocks ) {
if ( true === static::$has_submenus ) {
return static::$has_submenus;
}
foreach ( $inner_blocks as $inner_block ) {
$inner_block_content = $inner_block->render();
$p = new WP_HTML_Tag_Processor( $inner_block_content );
if ( $p->next_tag(
array(
'name' => 'LI',
'class_name' => 'has-child',
)
) ) {
return true;
// If this is a page list then work out if any of the pages have children.
if ( 'core/page-list' === $inner_block->name ) {
$all_pages = get_pages(
array(
'sort_column' => 'menu_order,post_title',
'order' => 'asc',
)
);
foreach ( (array) $all_pages as $page ) {
if ( $page->post_parent ) {
static::$has_submenus = true;
break;
}
}
}
// If this is a navigation submenu then we know we have submenus.
if ( 'core/navigation-submenu' === $inner_block->name ) {
static::$has_submenus = true;
break;
}
}
return false;
return static::$has_submenus;
}
/**
@ -96,7 +104,23 @@ class WP_Navigation_Block_Renderer {
* @return bool Returns whether or not a block needs a list item wrapper.
*/
private static function does_block_need_a_list_item_wrapper( $block ) {
return in_array( $block->name, static::$needs_list_item_wrapper, true );
/**
* Filter the list of blocks that need a list item wrapper.
*
* Affords the ability to customize which blocks need a list item wrapper when rendered
* within a core/navigation block.
* This is useful for blocks that are not list items but should be wrapped in a list
* item when used as a child of a navigation block.
*
* @since 6.5.0
*
* @param array $needs_list_item_wrapper The list of blocks that need a list item wrapper.
* @return array The list of blocks that need a list item wrapper.
*/
$needs_list_item_wrapper = apply_filters( 'block_core_navigation_listable_blocks', static::$needs_list_item_wrapper );
return in_array( $block->name, $needs_list_item_wrapper, true );
}
/**
@ -140,7 +164,9 @@ class WP_Navigation_Block_Renderer {
$is_list_open = false;
foreach ( $inner_blocks as $inner_block ) {
$is_list_item = in_array( $inner_block->name, static::$nav_blocks_wrapped_in_list_item, true );
$inner_block_markup = static::get_markup_for_inner_block( $inner_block );
$p = new WP_HTML_Tag_Processor( $inner_block_markup );
$is_list_item = $p->next_tag( 'LI' );
if ( $is_list_item && ! $is_list_open ) {
$is_list_open = true;
@ -155,7 +181,7 @@ class WP_Navigation_Block_Renderer {
$inner_blocks_html .= '</ul>';
}
$inner_blocks_html .= static::get_markup_for_inner_block( $inner_block );
$inner_blocks_html .= $inner_block_markup;
}
if ( $is_list_open ) {
@ -567,6 +593,17 @@ class WP_Navigation_Block_Renderer {
*/
private static function handle_view_script_module_loading( $attributes, $block, $inner_blocks ) {
if ( static::is_interactive( $attributes, $inner_blocks ) ) {
$suffix = wp_scripts_get_suffix();
if ( defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN ) {
$module_url = gutenberg_url( '/build/interactivity/navigation.min.js' );
}
wp_register_script_module(
'@wordpress/block-library/navigation',
isset( $module_url ) ? $module_url : includes_url( "blocks/navigation/view{$suffix}.js" ),
array( '@wordpress/interactivity' ),
defined( 'GUTENBERG_VERSION' ) ? GUTENBERG_VERSION : get_bloginfo( 'version' )
);
wp_enqueue_script_module( '@wordpress/block-library/navigation' );
}
}
@ -968,7 +1005,9 @@ function block_core_navigation_block_contains_core_navigation( $inner_blocks ) {
function block_core_navigation_get_fallback_blocks() {
$page_list_fallback = array(
array(
'blockName' => 'core/page-list',
'blockName' => 'core/page-list',
'innerContent' => array(),
'attrs' => array(),
),
);
@ -976,12 +1015,7 @@ function block_core_navigation_get_fallback_blocks() {
// If `core/page-list` is not registered then return empty blocks.
$fallback_blocks = $registry->is_registered( 'core/page-list' ) ? $page_list_fallback : array();
if ( class_exists( 'WP_Navigation_Fallback' ) ) {
$navigation_post = WP_Navigation_Fallback::get_fallback();
} else {
$navigation_post = Gutenberg_Navigation_Fallback::get_fallback();
}
$navigation_post = WP_Navigation_Fallback::get_fallback();
// Use the first non-empty Navigation as fallback if available.
if ( $navigation_post ) {
@ -1079,13 +1113,6 @@ function register_block_core_navigation() {
'render_callback' => 'render_block_core_navigation',
)
);
wp_register_script_module(
'@wordpress/block-library/navigation',
defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN ? gutenberg_url( '/build/interactivity/navigation.min.js' ) : includes_url( 'blocks/navigation/view.min.js' ),
array( '@wordpress/interactivity' ),
defined( 'GUTENBERG_VERSION' ) ? GUTENBERG_VERSION : get_bloginfo( 'version' )
);
}
add_action( 'init', 'register_block_core_navigation' );
@ -1418,9 +1445,14 @@ function block_core_navigation_update_ignore_hooked_blocks_meta( $post ) {
}
}
// Before adding our filter, we verify if it's already added in Core.
// However, during the build process, Gutenberg automatically prefixes our functions with "gutenberg_".
// Therefore, we concatenate the Core's function name to circumvent this prefix for our check.
$rest_insert_wp_navigation_core_callback = 'block_core_navigation_' . 'update_ignore_hooked_blocks_meta';
// Injection of hooked blocks into the Navigation block relies on some functions present in WP >= 6.5
// that are not present in Gutenberg's WP 6.5 compatibility layer.
if ( function_exists( 'get_hooked_block_markup' ) ) {
if ( function_exists( 'get_hooked_block_markup' ) && ! has_filter( 'rest_insert_wp_navigation', $rest_insert_wp_navigation_core_callback ) ) {
add_action( 'rest_insert_wp_navigation', 'block_core_navigation_update_ignore_hooked_blocks_meta', 10, 3 );
}
@ -1450,8 +1482,13 @@ function block_core_navigation_insert_hooked_blocks_into_rest_response( $respons
return $response;
}
// Before adding our filter, we verify if it's already added in Core.
// However, during the build process, Gutenberg automatically prefixes our functions with "gutenberg_".
// Therefore, we concatenate the Core's function name to circumvent this prefix for our check.
$rest_prepare_wp_navigation_core_callback = 'block_core_navigation_' . 'insert_hooked_blocks_into_rest_response';
// Injection of hooked blocks into the Navigation block relies on some functions present in WP >= 6.5
// that are not present in Gutenberg's WP 6.5 compatibility layer.
if ( function_exists( 'get_hooked_block_markup' ) ) {
if ( function_exists( 'get_hooked_block_markup' ) && ! has_filter( 'rest_prepare_wp_navigation', $rest_prepare_wp_navigation_core_callback ) ) {
add_filter( 'rest_prepare_wp_navigation', 'block_core_navigation_insert_hooked_blocks_into_rest_response', 10, 3 );
}

View File

@ -4,6 +4,19 @@
"name": "core/navigation",
"title": "Navigation",
"category": "theme",
"allowedBlocks": [
"core/navigation-link",
"core/search",
"core/social-links",
"core/page-list",
"core/spacer",
"core/home-link",
"core/site-title",
"core/site-logo",
"core/navigation-submenu",
"core/loginout",
"core/buttons"
],
"description": "A collection of blocks that allow visitors to get around your site.",
"keywords": [ "menu", "navigation", "links" ],
"textdomain": "default",

View File

@ -31,7 +31,6 @@ const interactivity_namespaceObject = x({ ["getContext"]: () => __WEBPACK_EXTERN
const DEFAULT_BLOCK = {
name: 'core/navigation-link'
};
const ALLOWED_BLOCKS = (/* unused pure expression or super */ null && (['core/navigation-link', 'core/search', 'core/social-links', 'core/page-list', 'core/spacer', 'core/home-link', 'core/site-title', 'core/site-logo', 'core/navigation-submenu', 'core/loginout', 'core/buttons']));
const PRIORITIZED_INSERTER_BLOCKS = (/* unused pure expression or super */ null && (['core/navigation-link/page', 'core/navigation-link']));
// These parameters must be kept aligned with those in
@ -245,5 +244,7 @@ const {
};
}
}
}, {
lock: true
});

View File

@ -1 +1 @@
import*as e from"@wordpress/interactivity";var t={d:(e,n)=>{for(var o in n)t.o(n,o)&&!t.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:n[o]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)};const n=(e=>{var n={};return t.d(n,e),n})({getContext:()=>e.getContext,getElement:()=>e.getElement,store:()=>e.store}),o=["a[href]",'input:not([disabled]):not([type="hidden"]):not([aria-hidden])',"select:not([disabled]):not([aria-hidden])","textarea:not([disabled]):not([aria-hidden])","button:not([disabled]):not([aria-hidden])","[contenteditable]",'[tabindex]:not([tabindex^="-"])'];document.addEventListener("click",(()=>{}));const{state:l,actions:c}=(0,n.store)("core/navigation",{state:{get roleAttribute(){return"overlay"===(0,n.getContext)().type&&l.isMenuOpen?"dialog":null},get ariaModal(){return"overlay"===(0,n.getContext)().type&&l.isMenuOpen?"true":null},get ariaLabel(){const e=(0,n.getContext)();return"overlay"===e.type&&l.isMenuOpen?e.ariaLabel:null},get isMenuOpen(){return Object.values(l.menuOpenedBy).filter(Boolean).length>0},get menuOpenedBy(){const e=(0,n.getContext)();return"overlay"===e.type?e.overlayOpenedBy:e.submenuOpenedBy}},actions:{openMenuOnHover(){const{type:e,overlayOpenedBy:t}=(0,n.getContext)();"submenu"===e&&0===Object.values(t||{}).filter(Boolean).length&&c.openMenu("hover")},closeMenuOnHover(){c.closeMenu("hover")},openMenuOnClick(){const e=(0,n.getContext)(),{ref:t}=(0,n.getElement)();e.previousFocus=t,c.openMenu("click")},closeMenuOnClick(){c.closeMenu("click"),c.closeMenu("focus")},openMenuOnFocus(){c.openMenu("focus")},toggleMenuOnClick(){const e=(0,n.getContext)(),{ref:t}=(0,n.getElement)();window.document.activeElement!==t&&t.focus();const{menuOpenedBy:o}=l;o.click||o.focus?(c.closeMenu("click"),c.closeMenu("focus")):(e.previousFocus=t,c.openMenu("click"))},handleMenuKeydown(e){const{type:t,firstFocusableElement:o,lastFocusableElement:s}=(0,n.getContext)();if(l.menuOpenedBy.click){if("Escape"===e?.key)return c.closeMenu("click"),void c.closeMenu("focus");"overlay"===t&&"Tab"===e.key&&(e.shiftKey&&window.document.activeElement===o?(e.preventDefault(),s.focus()):e.shiftKey||window.document.activeElement!==s||(e.preventDefault(),o.focus()))}},handleMenuFocusout(e){const{modal:t}=(0,n.getContext)();(null===e.relatedTarget||!t?.contains(e.relatedTarget)&&e.target!==window.document.activeElement)&&(c.closeMenu("click"),c.closeMenu("focus"))},openMenu(e="click"){const{type:t}=(0,n.getContext)();l.menuOpenedBy[e]=!0,"overlay"===t&&document.documentElement.classList.add("has-modal-open")},closeMenu(e="click"){const t=(0,n.getContext)();l.menuOpenedBy[e]=!1,l.isMenuOpen||(t.modal?.contains(window.document.activeElement)&&t.previousFocus?.focus(),t.modal=null,t.previousFocus=null,"overlay"===t.type&&document.documentElement.classList.remove("has-modal-open"))}},callbacks:{initMenu(){const e=(0,n.getContext)(),{ref:t}=(0,n.getElement)();if(l.isMenuOpen){const n=t.querySelectorAll(o);e.modal=t,e.firstFocusableElement=n[0],e.lastFocusableElement=n[n.length-1]}},focusFirstElement(){const{ref:e}=(0,n.getElement)();if(l.isMenuOpen){const t=e.querySelectorAll(o);t?.[0]?.focus()}},initNav(){const e=(0,n.getContext)(),t=window.matchMedia("(max-width: 600px)");function o(t){e.isCollapsed=t.matches}return e.isCollapsed=t.matches,t.addEventListener("change",o),()=>{t.removeEventListener("change",o)}}}});
import*as e from"@wordpress/interactivity";var t={d:(e,n)=>{for(var o in n)t.o(n,o)&&!t.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:n[o]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)};const n=(e=>{var n={};return t.d(n,e),n})({getContext:()=>e.getContext,getElement:()=>e.getElement,store:()=>e.store}),o=["a[href]",'input:not([disabled]):not([type="hidden"]):not([aria-hidden])',"select:not([disabled]):not([aria-hidden])","textarea:not([disabled]):not([aria-hidden])","button:not([disabled]):not([aria-hidden])","[contenteditable]",'[tabindex]:not([tabindex^="-"])'];document.addEventListener("click",(()=>{}));const{state:l,actions:c}=(0,n.store)("core/navigation",{state:{get roleAttribute(){return"overlay"===(0,n.getContext)().type&&l.isMenuOpen?"dialog":null},get ariaModal(){return"overlay"===(0,n.getContext)().type&&l.isMenuOpen?"true":null},get ariaLabel(){const e=(0,n.getContext)();return"overlay"===e.type&&l.isMenuOpen?e.ariaLabel:null},get isMenuOpen(){return Object.values(l.menuOpenedBy).filter(Boolean).length>0},get menuOpenedBy(){const e=(0,n.getContext)();return"overlay"===e.type?e.overlayOpenedBy:e.submenuOpenedBy}},actions:{openMenuOnHover(){const{type:e,overlayOpenedBy:t}=(0,n.getContext)();"submenu"===e&&0===Object.values(t||{}).filter(Boolean).length&&c.openMenu("hover")},closeMenuOnHover(){c.closeMenu("hover")},openMenuOnClick(){const e=(0,n.getContext)(),{ref:t}=(0,n.getElement)();e.previousFocus=t,c.openMenu("click")},closeMenuOnClick(){c.closeMenu("click"),c.closeMenu("focus")},openMenuOnFocus(){c.openMenu("focus")},toggleMenuOnClick(){const e=(0,n.getContext)(),{ref:t}=(0,n.getElement)();window.document.activeElement!==t&&t.focus();const{menuOpenedBy:o}=l;o.click||o.focus?(c.closeMenu("click"),c.closeMenu("focus")):(e.previousFocus=t,c.openMenu("click"))},handleMenuKeydown(e){const{type:t,firstFocusableElement:o,lastFocusableElement:s}=(0,n.getContext)();if(l.menuOpenedBy.click){if("Escape"===e?.key)return c.closeMenu("click"),void c.closeMenu("focus");"overlay"===t&&"Tab"===e.key&&(e.shiftKey&&window.document.activeElement===o?(e.preventDefault(),s.focus()):e.shiftKey||window.document.activeElement!==s||(e.preventDefault(),o.focus()))}},handleMenuFocusout(e){const{modal:t}=(0,n.getContext)();(null===e.relatedTarget||!t?.contains(e.relatedTarget)&&e.target!==window.document.activeElement)&&(c.closeMenu("click"),c.closeMenu("focus"))},openMenu(e="click"){const{type:t}=(0,n.getContext)();l.menuOpenedBy[e]=!0,"overlay"===t&&document.documentElement.classList.add("has-modal-open")},closeMenu(e="click"){const t=(0,n.getContext)();l.menuOpenedBy[e]=!1,l.isMenuOpen||(t.modal?.contains(window.document.activeElement)&&t.previousFocus?.focus(),t.modal=null,t.previousFocus=null,"overlay"===t.type&&document.documentElement.classList.remove("has-modal-open"))}},callbacks:{initMenu(){const e=(0,n.getContext)(),{ref:t}=(0,n.getElement)();if(l.isMenuOpen){const n=t.querySelectorAll(o);e.modal=t,e.firstFocusableElement=n[0],e.lastFocusableElement=n[n.length-1]}},focusFirstElement(){const{ref:e}=(0,n.getElement)();if(l.isMenuOpen){const t=e.querySelectorAll(o);t?.[0]?.focus()}},initNav(){const e=(0,n.getContext)(),t=window.matchMedia("(max-width: 600px)");function o(t){e.isCollapsed=t.matches}return e.isCollapsed=t.matches,t.addEventListener("change",o),()=>{t.removeEventListener("change",o)}}}},{lock:!0});

View File

@ -11,7 +11,10 @@
"supports": {
"customClassName": false,
"className": false,
"html": false
"html": false,
"interactivity": {
"clientNavigation": true
}
},
"editorStyle": "wp-block-nextpage-editor"
}

View File

@ -45,7 +45,10 @@
"html": false,
"lock": false,
"inserter": false,
"__experimentalToolbar": false
"__experimentalToolbar": false,
"interactivity": {
"clientNavigation": true
}
},
"editorStyle": "wp-block-page-list-editor",
"style": "wp-block-page-list"

View File

@ -4,6 +4,7 @@
"name": "core/page-list",
"title": "Page List",
"category": "widgets",
"allowedBlocks": [ "core/page-list-item" ],
"description": "Display a list of all pages.",
"keywords": [ "menu", "navigation" ],
"textdomain": "default",
@ -47,6 +48,9 @@
"__experimentalDefaultControls": {
"fontSize": true
}
},
"interactivity": {
"clientNavigation": true
}
},
"editorStyle": "wp-block-page-list-editor",

View File

@ -64,7 +64,10 @@
}
},
"__experimentalSelector": "p",
"__unstablePasteTextInline": true
"__unstablePasteTextInline": true,
"interactivity": {
"clientNavigation": true
}
},
"editorStyle": "wp-block-paragraph-editor",
"style": "wp-block-paragraph"

View File

@ -8,7 +8,10 @@
"supports": {
"html": false,
"inserter": false,
"renaming": false
"renaming": false,
"interactivity": {
"clientNavigation": true
}
},
"textdomain": "default",
"attributes": {

View File

@ -37,6 +37,9 @@
"__experimentalDefaultControls": {
"fontSize": true
}
},
"interactivity": {
"clientNavigation": true
}
}
}

View File

@ -47,6 +47,9 @@
"__experimentalDefaultControls": {
"fontSize": true
}
},
"interactivity": {
"clientNavigation": true
}
}
}

View File

@ -61,6 +61,9 @@
"background": true,
"text": true
}
},
"interactivity": {
"clientNavigation": true
}
},
"style": "wp-block-post-author"

View File

@ -0,0 +1,4 @@
.wp-block-post-content.wp-block-post-content{
-webkit-user-select:none;
user-select:none;
}

View File

@ -0,0 +1 @@
.wp-block-post-content.wp-block-post-content{-webkit-user-select:none;user-select:none}

View File

@ -0,0 +1,4 @@
.wp-block-post-content.wp-block-post-content{
-webkit-user-select:none;
user-select:none;
}

View File

@ -0,0 +1 @@
.wp-block-post-content.wp-block-post-content{-webkit-user-select:none;user-select:none}

View File

@ -50,6 +50,9 @@
"__experimentalDefaultControls": {
"fontSize": true
}
},
"interactivity": {
"clientNavigation": true
}
}
}

View File

@ -50,6 +50,9 @@
"__experimentalDefaultControls": {
"fontSize": true
}
},
"interactivity": {
"clientNavigation": true
}
},
"editorStyle": "wp-block-post-excerpt-editor",

View File

@ -81,6 +81,9 @@
"spacing": {
"margin": true,
"padding": true
},
"interactivity": {
"clientNavigation": true
}
},
"editorStyle": "wp-block-post-featured-image-editor",

View File

@ -99,9 +99,6 @@ function render_block_core_post_navigation_link( $attributes, $content ) {
}
}
$in_same_term = isset( $attributes['inSameTerm'] ) ? $attributes['inSameTerm'] : false;
$taxonomy = isset( $attributes['taxonomy'] ) && $in_same_term ? $attributes['taxonomy'] : '';
/*
* The dynamic portion of the function name, `$navigation_type`,
* Refers to the type of adjacency, 'next' or 'previous'.
@ -111,8 +108,8 @@ function render_block_core_post_navigation_link( $attributes, $content ) {
*/
$get_link_function = "get_{$navigation_type}_post_link";
if ( $in_same_term ) {
$content = $get_link_function( $format, $link, $in_same_term, '', $taxonomy );
if ( ! empty( $attributes['taxonomy'] ) ) {
$content = $get_link_function( $format, $link, true, '', $attributes['taxonomy'] );
} else {
$content = $get_link_function( $format, $link );
}

View File

@ -29,9 +29,6 @@
"type": "string",
"default": "none"
},
"inSameTerm": {
"type": "boolean"
},
"taxonomy": {
"type": "string",
"default": ""
@ -57,6 +54,9 @@
"__experimentalDefaultControls": {
"fontSize": true
}
},
"interactivity": {
"clientNavigation": true
}
},
"style": "wp-block-post-navigation-link"

View File

@ -48,6 +48,9 @@
"__experimentalDefaultControls": {
"blockGap": true
}
},
"interactivity": {
"clientNavigation": true
}
},
"style": "wp-block-post-template",

View File

@ -63,7 +63,7 @@ function render_block_core_post_terms( $attributes, $content, $block ) {
*
* @return array The available variations for the block.
*/
function build_post_term_block_variations() {
function block_core_post_terms_build_variations() {
$taxonomies = get_taxonomies(
array(
'publicly_queryable' => true,
@ -116,7 +116,7 @@ function register_block_core_post_terms() {
__DIR__ . '/post-terms',
array(
'render_callback' => 'render_block_core_post_terms',
'variation_callback' => 'build_post_term_block_variations',
'variation_callback' => 'block_core_post_terms_build_variations',
)
);
}

View File

@ -54,6 +54,9 @@
"__experimentalDefaultControls": {
"fontSize": true
}
},
"interactivity": {
"clientNavigation": true
}
},
"style": "wp-block-post-terms"

View File

@ -57,6 +57,9 @@
"__experimentalDefaultControls": {
"fontSize": true
}
},
"interactivity": {
"clientNavigation": true
}
},
"style": "wp-block-post-title"

View File

@ -40,6 +40,9 @@
"__experimentalDefaultControls": {
"fontSize": true
}
},
"interactivity": {
"clientNavigation": true
}
},
"style": "wp-block-preformatted"

View File

@ -69,6 +69,9 @@
"fontSize": "1.5em",
"lineHeight": "1.6"
}
},
"interactivity": {
"clientNavigation": true
}
},
"editorStyle": "wp-block-pullquote-editor",

View File

@ -28,6 +28,9 @@
"__experimentalDefaultControls": {
"fontSize": true
}
},
"interactivity": {
"clientNavigation": true
}
}
}

View File

@ -41,6 +41,9 @@
"__experimentalDefaultControls": {
"fontSize": true
}
},
"interactivity": {
"clientNavigation": true
}
}
}

View File

@ -36,6 +36,9 @@
"__experimentalDefaultControls": {
"fontSize": true
}
},
"interactivity": {
"clientNavigation": true
}
},
"editorStyle": "wp-block-query-pagination-numbers-editor"

View File

@ -41,6 +41,9 @@
"__experimentalDefaultControls": {
"fontSize": true
}
},
"interactivity": {
"clientNavigation": true
}
}
}

View File

@ -4,7 +4,12 @@
"name": "core/query-pagination",
"title": "Pagination",
"category": "theme",
"parent": [ "core/query" ],
"ancestor": [ "core/query" ],
"allowedBlocks": [
"core/query-pagination-previous",
"core/query-pagination-numbers",
"core/query-pagination-next"
],
"description": "Displays a paginated navigation to next/previous set of posts, when applicable.",
"textdomain": "default",
"attributes": {
@ -54,6 +59,9 @@
"__experimentalDefaultControls": {
"fontSize": true
}
},
"interactivity": {
"clientNavigation": true
}
},
"editorStyle": "wp-block-query-pagination-editor",

View File

@ -52,6 +52,9 @@
"__experimentalDefaultControls": {
"fontSize": true
}
},
"interactivity": {
"clientNavigation": true
}
},
"style": "wp-block-query-title"

View File

@ -17,11 +17,33 @@
* @return string Returns the modified output of the query block.
*/
function render_block_core_query( $attributes, $content, $block ) {
$is_interactive = isset( $attributes['enhancedPagination'] ) && true === $attributes['enhancedPagination'] && isset( $attributes['queryId'] );
$is_interactive = isset( $attributes['enhancedPagination'] )
&& true === $attributes['enhancedPagination']
&& isset( $attributes['queryId'] );
// Enqueue the script module and add the necessary directives if the block is
// interactive.
if ( $is_interactive ) {
$suffix = wp_scripts_get_suffix();
if ( defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN ) {
$module_url = gutenberg_url( '/build/interactivity/query.min.js' );
}
wp_register_script_module(
'@wordpress/block-library/query',
isset( $module_url ) ? $module_url : includes_url( "blocks/query/view{$suffix}.js" ),
array(
array(
'id' => '@wordpress/interactivity',
'import' => 'static',
),
array(
'id' => '@wordpress/interactivity-router',
'import' => 'dynamic',
),
),
defined( 'GUTENBERG_VERSION' ) ? GUTENBERG_VERSION : get_bloginfo( 'version' )
);
wp_enqueue_script_module( '@wordpress/block-library/query' );
$p = new WP_HTML_Tag_Processor( $content );
@ -30,43 +52,8 @@ function render_block_core_query( $attributes, $content, $block ) {
$p->set_attribute( 'data-wp-interactive', '{"namespace":"core/query"}' );
$p->set_attribute( 'data-wp-router-region', 'query-' . $attributes['queryId'] );
$p->set_attribute( 'data-wp-init', 'callbacks.setQueryRef' );
// Use context to send translated strings.
$p->set_attribute(
'data-wp-context',
wp_json_encode(
array(
'loadingText' => __( 'Loading page, please wait.' ),
'loadedText' => __( 'Page Loaded.' ),
),
JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP
)
);
$p->set_attribute( 'data-wp-context', '{}' );
$content = $p->get_updated_html();
// Mark the block as interactive.
$block->block_type->supports['interactivity'] = true;
// Add a div to announce messages using `aria-live`.
$html_tag = 'div';
if ( ! empty( $attributes['tagName'] ) ) {
$html_tag = esc_attr( $attributes['tagName'] );
}
$last_tag_position = strripos( $content, '</' . $html_tag . '>' );
$content = substr_replace(
$content,
'<div
class="screen-reader-text"
aria-live="polite"
data-wp-text="context.message"
></div>
<div
class="wp-block-query__enhanced-pagination-animation"
data-wp-class--start-animation="state.startAnimation"
data-wp-class--finish-animation="state.finishAnimation"
></div>',
$last_tag_position,
0
);
}
}
@ -98,22 +85,6 @@ function register_block_core_query() {
'render_callback' => 'render_block_core_query',
)
);
wp_register_script_module(
'@wordpress/block-library/query',
defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN ? gutenberg_url( '/build/interactivity/query.min.js' ) : includes_url( 'blocks/query/view.min.js' ),
array(
array(
'id' => '@wordpress/interactivity',
'import' => 'static',
),
array(
'id' => '@wordpress/interactivity-router',
'import' => 'dynamic',
),
),
defined( 'GUTENBERG_VERSION' ) ? GUTENBERG_VERSION : get_bloginfo( 'version' )
);
}
add_action( 'init', 'register_block_core_query' );
@ -133,10 +104,18 @@ function block_core_query_disable_enhanced_pagination( $parsed_block ) {
static $dirty_enhanced_queries = array();
static $render_query_callback = null;
$is_interactive = isset( $parsed_block['attrs']['enhancedPagination'] ) && true === $parsed_block['attrs']['enhancedPagination'] && isset( $parsed_block['attrs']['queryId'] );
$block_name = $parsed_block['blockName'];
$block_name = $parsed_block['blockName'];
$block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block_name );
$has_enhanced_pagination = isset( $parsed_block['attrs']['enhancedPagination'] ) && true === $parsed_block['attrs']['enhancedPagination'] && isset( $parsed_block['attrs']['queryId'] );
/*
* Client side navigation can be true in two states:
* - supports.interactivity = true;
* - supports.interactivity.clientNavigation = true;
*/
$supports_client_navigation = ( isset( $block_type->supports['interactivity']['clientNavigation'] ) && true === $block_type->supports['interactivity']['clientNavigation'] )
|| ( isset( $block_type->supports['interactivity'] ) && true === $block_type->supports['interactivity'] );
if ( 'core/query' === $block_name && $is_interactive ) {
if ( 'core/query' === $block_name && $has_enhanced_pagination ) {
$enhanced_query_stack[] = $parsed_block['attrs']['queryId'];
if ( ! isset( $render_query_callback ) ) {
@ -151,18 +130,15 @@ function block_core_query_disable_enhanced_pagination( $parsed_block ) {
* @return string Returns the modified output of the query block.
*/
$render_query_callback = static function ( $content, $block ) use ( &$enhanced_query_stack, &$dirty_enhanced_queries, &$render_query_callback ) {
$is_interactive = isset( $block['attrs']['enhancedPagination'] ) && true === $block['attrs']['enhancedPagination'] && isset( $block['attrs']['queryId'] );
$has_enhanced_pagination = isset( $block['attrs']['enhancedPagination'] ) && true === $block['attrs']['enhancedPagination'] && isset( $block['attrs']['queryId'] );
if ( ! $is_interactive ) {
if ( ! $has_enhanced_pagination ) {
return $content;
}
if ( isset( $dirty_enhanced_queries[ $block['attrs']['queryId'] ] ) ) {
$p = new WP_HTML_Tag_Processor( $content );
if ( $p->next_tag() ) {
$p->set_attribute( 'data-wp-navigation-disabled', 'true' );
}
$content = $p->get_updated_html();
// Disable navigation in the router store config.
wp_interactivity_config( 'core/router', array( 'clientNavigationDisabled' => true ) );
$dirty_enhanced_queries[ $block['attrs']['queryId'] ] = null;
}
@ -181,7 +157,7 @@ function block_core_query_disable_enhanced_pagination( $parsed_block ) {
} elseif (
! empty( $enhanced_query_stack ) &&
isset( $block_name ) &&
( ! str_starts_with( $block_name, 'core/' ) || 'core/post-content' === $block_name )
( ! $supports_client_navigation )
) {
foreach ( $enhanced_query_stack as $query_id ) {
$dirty_enhanced_queries[ $query_id ] = true;

Some files were not shown because too many files have changed in this diff Show More