From e5d2a5ab47d8985b2d4a3439c2dcc8836c4c60bb Mon Sep 17 00:00:00 2001
From: George Mamadashvili
Date: Mon, 3 Jun 2024 18:44:32 +0400
Subject: [PATCH 01/17] Inserter: Update Openverse API URLs (#62241)
Co-authored-by: Mamaduka
Co-authored-by: youknowriad
Co-authored-by: tyxla
Co-authored-by: zackkrida
---
docs/reference-guides/data/data-core-block-editor.md | 2 +-
packages/block-editor/src/store/actions.js | 2 +-
.../src/components/block-editor/inserter-media-categories.js | 4 +---
packages/editor/src/components/media-categories/index.js | 4 +---
4 files changed, 4 insertions(+), 8 deletions(-)
diff --git a/docs/reference-guides/data/data-core-block-editor.md b/docs/reference-guides/data/data-core-block-editor.md
index 862a8b2d8a06a..f687eb79732b5 100644
--- a/docs/reference-guides/data/data-core-block-editor.md
+++ b/docs/reference-guides/data/data-core-block-editor.md
@@ -1439,7 +1439,7 @@ wp.data.dispatch( 'core/block-editor' ).registerInserterMediaCategory( {
per_page: 'page_size',
search: 'q',
};
- const url = new URL( 'https://api.openverse.engineering/v1/images/' );
+ const url = new URL( 'https://api.openverse.org/v1/images/' );
Object.entries( finalQuery ).forEach( ( [ key, value ] ) => {
const queryKey = mapFromInserterMediaRequest[ key ] || key;
url.searchParams.set( queryKey, value );
diff --git a/packages/block-editor/src/store/actions.js b/packages/block-editor/src/store/actions.js
index db2c615dd5d6c..d44fa3e69f86a 100644
--- a/packages/block-editor/src/store/actions.js
+++ b/packages/block-editor/src/store/actions.js
@@ -2010,7 +2010,7 @@ export function __unstableSetTemporarilyEditingAsBlocks(
* per_page: 'page_size',
* search: 'q',
* };
- * const url = new URL( 'https://api.openverse.engineering/v1/images/' );
+ * const url = new URL( 'https://api.openverse.org/v1/images/' );
* Object.entries( finalQuery ).forEach( ( [ key, value ] ) => {
* const queryKey = mapFromInserterMediaRequest[ key ] || key;
* url.searchParams.set( queryKey, value );
diff --git a/packages/edit-site/src/components/block-editor/inserter-media-categories.js b/packages/edit-site/src/components/block-editor/inserter-media-categories.js
index af591d1fa2468..7ebc771126122 100644
--- a/packages/edit-site/src/components/block-editor/inserter-media-categories.js
+++ b/packages/edit-site/src/components/block-editor/inserter-media-categories.js
@@ -191,9 +191,7 @@ const inserterMediaCategories = [
per_page: 'page_size',
search: 'q',
};
- const url = new URL(
- 'https://api.openverse.engineering/v1/images/'
- );
+ const url = new URL( 'https://api.openverse.org/v1/images/' );
Object.entries( finalQuery ).forEach( ( [ key, value ] ) => {
const queryKey = mapFromInserterMediaRequest[ key ] || key;
url.searchParams.set( queryKey, value );
diff --git a/packages/editor/src/components/media-categories/index.js b/packages/editor/src/components/media-categories/index.js
index 345f5c5c86e2c..be1b2bdc2d672 100644
--- a/packages/editor/src/components/media-categories/index.js
+++ b/packages/editor/src/components/media-categories/index.js
@@ -191,9 +191,7 @@ const inserterMediaCategories = [
per_page: 'page_size',
search: 'q',
};
- const url = new URL(
- 'https://api.openverse.engineering/v1/images/'
- );
+ const url = new URL( 'https://api.openverse.org/v1/images/' );
Object.entries( finalQuery ).forEach( ( [ key, value ] ) => {
const queryKey = mapFromInserterMediaRequest[ key ] || key;
url.searchParams.set( queryKey, value );
From 0bfd56b340405c2869914a0154e8058b64f1bb02 Mon Sep 17 00:00:00 2001
From: Lena Morita
Date: Tue, 4 Jun 2024 05:20:03 +0900
Subject: [PATCH 02/17] Add lint rule for inaccessible disabled `Button`
(#62080)
* Add lint rule for inaccessible disabled `Button`
* Exclude react native files
* Include files in root `storybook` folder
* Fix in Storybook editor playground (matches actual behavior)
* Fix in install block button (is clearly a busy state)
* Ignore in gallery image reordering buttons
* Fix in LinkControl copy link button (aleviates confusion)
* Ignore in edit-site pagination buttons (not confusing, and useful)
* Fix in enable custom fields (is clearly a busy state)
* Fix in DataViews list view
Empty action menu should still be perceivable to aleviate confusion, and does not clutter tab order due to Composite use.
* Fix in DataViews CompactItemActions (is dropdown trigger)
* Fix in template part title modal
disabled and aria-disabled are set with an identical condition, which doesn't make sense but signals the intent to keep it focusable.
* Fix in PageList block (should be perceivable, esp. because the description is always there)
* Fix in ConvertToLinksModal button (should be perceivable, and doesn't clutter tab order)
* Fix in edit-site "Apply globally" button (should be perceivable, and doesn't clutter tab order)
* Fix in edit-site nav menu rename modal (should be perceivable to signal that input is invalid)
* Fix in RevisionsButtons (button is never visible when `areStylesEqual`)
* Fix in RevisionsButtons (contains important info and should be perceivable)
* Fix in GlobalStylesSidebar (should be perceivable)
* Fix in PostPublishPanel cancel button (can cause focus loss)
* Fix in PostPreviewButton (should be perceivable)
* Defer decision in ButtonBlockAppender
* Fix in reusable blocks import form (should be perceivable, can cause focus loss)
* Adapt test for PostPreviewButton
* Improve rigidity of accessible disabled detection in test
* Add disable reason for ButtonBlockAppender
Co-authored-by: mirka <0mirka00@git.wordpress.org>
Co-authored-by: tyxla
Co-authored-by: DaniGuardiola
---
.eslintrc.js | 18 ++++++++++++++++++
.../get-install-missing/install-button.js | 1 +
.../components/button-block-appender/index.js | 2 ++
.../components/link-control/link-preview.js | 1 +
.../src/gallery/v1/gallery-image.js | 8 ++++++++
.../src/page-list/convert-to-links-modal.js | 1 +
packages/block-library/src/page-list/edit.js | 1 +
.../src/template-part/edit/title-modal.js | 2 +-
packages/dataviews/src/item-actions.tsx | 1 +
packages/dataviews/src/view-list.tsx | 1 +
.../preferences-modal/enable-custom-fields.js | 1 +
.../components/global-styles-sidebar/index.js | 2 ++
.../screen-revisions/revisions-buttons.js | 2 +-
.../src/components/pagination/index.js | 8 ++++++++
.../rename-modal.js | 1 +
.../push-changes-to-global-styles/index.js | 1 +
.../components/post-preview-button/index.js | 1 +
.../post-preview-button/test/index.js | 12 ++++++++++--
.../src/components/post-publish-panel/index.js | 1 +
.../src/components/import-form/index.js | 1 +
.../stories/playground/with-undo-redo/index.js | 2 ++
21 files changed, 64 insertions(+), 4 deletions(-)
diff --git a/.eslintrc.js b/.eslintrc.js
index 9240b96c033b4..e997e7804beac 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -253,6 +253,24 @@ module.exports = {
],
},
},
+ {
+ files: [
+ 'packages/*/src/**/*.[tj]s?(x)',
+ 'storybook/stories/**/*.[tj]s?(x)',
+ ],
+ excludedFiles: [ '**/*.native.js' ],
+ rules: {
+ 'no-restricted-syntax': [
+ 'error',
+ {
+ selector:
+ 'JSXOpeningElement[name.name="Button"]:not(:has(JSXAttribute[name.name="__experimentalIsFocusable"])) JSXAttribute[name.name="disabled"]',
+ message:
+ '`disabled` used without the `__experimentalIsFocusable` prop. Disabling a control without maintaining focusability can cause accessibility issues, by hiding their presence from screen reader users, or preventing focus from returning to a trigger element. (Ignore this error if you truly mean to disable.)',
+ },
+ ],
+ },
+ },
{
files: [
// Components package.
diff --git a/packages/block-directory/src/plugins/get-install-missing/install-button.js b/packages/block-directory/src/plugins/get-install-missing/install-button.js
index 2dc01184bdeb4..075fed360c14c 100644
--- a/packages/block-directory/src/plugins/get-install-missing/install-button.js
+++ b/packages/block-directory/src/plugins/get-install-missing/install-button.js
@@ -42,6 +42,7 @@ export default function InstallButton( { attributes, block, clientId } ) {
}
} )
}
+ __experimentalIsFocusable
disabled={ isInstallingBlock }
isBusy={ isInstallingBlock }
variant="primary"
diff --git a/packages/block-editor/src/components/button-block-appender/index.js b/packages/block-editor/src/components/button-block-appender/index.js
index 974f48e61bc28..cd1289c897824 100644
--- a/packages/block-editor/src/components/button-block-appender/index.js
+++ b/packages/block-editor/src/components/button-block-appender/index.js
@@ -60,6 +60,8 @@ function ButtonBlockAppender(
onClick={ onToggle }
aria-haspopup={ isToggleButton ? 'true' : undefined }
aria-expanded={ isToggleButton ? isOpen : undefined }
+ // Disable reason: There shouldn't be a case where this button is disabled but not visually hidden.
+ // eslint-disable-next-line no-restricted-syntax
disabled={ disabled }
label={ label }
>
diff --git a/packages/block-editor/src/components/link-control/link-preview.js b/packages/block-editor/src/components/link-control/link-preview.js
index 867b69356eb9d..fb4b3658e2a4f 100644
--- a/packages/block-editor/src/components/link-control/link-preview.js
+++ b/packages/block-editor/src/components/link-control/link-preview.js
@@ -149,6 +149,7 @@ export default function LinkPreview( {
isEmptyURL || showIconLabels ? '' : ': ' + value.url
) }
ref={ ref }
+ __experimentalIsFocusable
disabled={ isEmptyURL }
size="compact"
/>
diff --git a/packages/block-library/src/gallery/v1/gallery-image.js b/packages/block-library/src/gallery/v1/gallery-image.js
index 368d5da55c4ac..5384944b2335d 100644
--- a/packages/block-library/src/gallery/v1/gallery-image.js
+++ b/packages/block-library/src/gallery/v1/gallery-image.js
@@ -222,6 +222,8 @@ class GalleryImage extends Component {
onClick={ isFirstItem ? undefined : onMoveBackward }
label={ __( 'Move image backward' ) }
aria-disabled={ isFirstItem }
+ // Disable reason: Truly disable when image is not selected.
+ // eslint-disable-next-line no-restricted-syntax
disabled={ ! isSelected }
/>
@@ -237,12 +241,16 @@ class GalleryImage extends Component {
icon={ edit }
onClick={ this.onEdit }
label={ __( 'Replace image' ) }
+ // Disable reason: Truly disable when image is not selected.
+ // eslint-disable-next-line no-restricted-syntax
disabled={ ! isSelected }
/>
diff --git a/packages/block-library/src/page-list/convert-to-links-modal.js b/packages/block-library/src/page-list/convert-to-links-modal.js
index 33ee22045b824..12277bee01faf 100644
--- a/packages/block-library/src/page-list/convert-to-links-modal.js
+++ b/packages/block-library/src/page-list/convert-to-links-modal.js
@@ -36,6 +36,7 @@ export function ConvertToLinksModal( { onClick, onClose, disabled } ) {
) : (
changePage( 1 ) }
+ // Disable reason: Would not cause confusion, and allows quicker access to a relevant nav button.
+ // eslint-disable-next-line no-restricted-syntax
disabled={ disabled || currentPage === 1 }
aria-label={ __( 'First page' ) }
>
@@ -54,6 +56,8 @@ export default function Pagination( {
changePage( currentPage - 1 ) }
+ // Disable reason: Would not cause confusion, and allows quicker access to a relevant nav button.
+ // eslint-disable-next-line no-restricted-syntax
disabled={ disabled || currentPage === 1 }
aria-label={ __( 'Previous page' ) }
>
@@ -72,6 +76,8 @@ export default function Pagination( {
changePage( currentPage + 1 ) }
+ // Disable reason: Would not cause confusion, and allows quicker access to a relevant nav button.
+ // eslint-disable-next-line no-restricted-syntax
disabled={ disabled || currentPage === numPages }
aria-label={ __( 'Next page' ) }
>
@@ -80,6 +86,8 @@ export default function Pagination( {
changePage( numPages ) }
+ // Disable reason: Would not cause confusion, and allows quicker access to a relevant nav button.
+ // eslint-disable-next-line no-restricted-syntax
disabled={ disabled || currentPage === numPages }
aria-label={ __( 'Last page' ) }
>
diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menu/rename-modal.js b/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menu/rename-modal.js
index a2281804bcb72..d290a40516bf0 100644
--- a/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menu/rename-modal.js
+++ b/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menu/rename-modal.js
@@ -43,6 +43,7 @@ export default function RenameModal( { menuTitle, onClose, onSave } ) {
diff --git a/packages/editor/src/components/post-preview-button/index.js b/packages/editor/src/components/post-preview-button/index.js
index 110de5858af38..e517ac0e8a0fb 100644
--- a/packages/editor/src/components/post-preview-button/index.js
+++ b/packages/editor/src/components/post-preview-button/index.js
@@ -183,6 +183,7 @@ export default function PostPreviewButton( {
className={ className || 'editor-post-preview' }
href={ href }
target={ targetId }
+ __experimentalIsFocusable
disabled={ ! isSaveable }
onClick={ openPreviewWindow }
role={ role }
diff --git a/packages/editor/src/components/post-preview-button/test/index.js b/packages/editor/src/components/post-preview-button/test/index.js
index e34c05caa178b..bb51f302edf50 100644
--- a/packages/editor/src/components/post-preview-button/test/index.js
+++ b/packages/editor/src/components/post-preview-button/test/index.js
@@ -139,12 +139,16 @@ describe( 'PostPreviewButton', () => {
).toBeInTheDocument();
} );
- it( 'should be disabled if post is not saveable.', () => {
+ it( 'should be accessibly disabled if post is not saveable.', () => {
mockUseSelect( { isEditedPostSaveable: () => false } );
render( );
- expect( screen.getByRole( 'button' ) ).toBeDisabled();
+ expect( screen.getByRole( 'button' ) ).toBeEnabled();
+ expect( screen.getByRole( 'button' ) ).toHaveAttribute(
+ 'aria-disabled',
+ 'true'
+ );
} );
it( 'should not be disabled if post is saveable.', () => {
@@ -153,6 +157,10 @@ describe( 'PostPreviewButton', () => {
render( );
expect( screen.getByRole( 'button' ) ).toBeEnabled();
+ expect( screen.getByRole( 'button' ) ).not.toHaveAttribute(
+ 'aria-disabled',
+ 'true'
+ );
} );
it( 'should set `href` to edited post preview link if specified.', () => {
diff --git a/packages/editor/src/components/post-publish-panel/index.js b/packages/editor/src/components/post-publish-panel/index.js
index 4d59133966759..31e838575c087 100644
--- a/packages/editor/src/components/post-publish-panel/index.js
+++ b/packages/editor/src/components/post-publish-panel/index.js
@@ -93,6 +93,7 @@ export class PostPublishPanel extends Component {
From 9cee9c40df2f250fa1ca29e7d23f442c7e34a2a0 Mon Sep 17 00:00:00 2001
From: Amit Raj <77401999+amitraj2203@users.noreply.github.com>
Date: Tue, 4 Jun 2024 03:45:04 +0530
Subject: [PATCH 03/17] Add doc for WordCount component (#62217)
---
packages/editor/README.md | 6 +++++-
packages/editor/src/components/word-count/index.js | 5 +++++
2 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/packages/editor/README.md b/packages/editor/README.md
index 6e887b6c0b82e..d4161f9bac626 100644
--- a/packages/editor/README.md
+++ b/packages/editor/README.md
@@ -1592,7 +1592,11 @@ Undocumented declaration.
### WordCount
-Undocumented declaration.
+Renders the word count of the post content.
+
+_Returns_
+
+- `JSX.Element|null`: The rendered WordCount component.
### WritingFlow
diff --git a/packages/editor/src/components/word-count/index.js b/packages/editor/src/components/word-count/index.js
index 1aad38d62132d..aab562b46b89f 100644
--- a/packages/editor/src/components/word-count/index.js
+++ b/packages/editor/src/components/word-count/index.js
@@ -10,6 +10,11 @@ import { count as wordCount } from '@wordpress/wordcount';
*/
import { store as editorStore } from '../../store';
+/**
+ * Renders the word count of the post content.
+ *
+ * @return {JSX.Element|null} The rendered WordCount component.
+ */
export default function WordCount() {
const content = useSelect(
( select ) => select( editorStore ).getEditedPostAttribute( 'content' ),
From 6e2d9c54113b38463f3908b07c02ab3e021472c7 Mon Sep 17 00:00:00 2001
From: Ramon
Date: Tue, 4 Jun 2024 10:00:53 +1000
Subject: [PATCH 04/17] Site Export: ensure that the export endpoint uses
Gutenberg theme classes (#61561)
* This ensures that any theme exports get the benefit of the latest changes to theme json and resolver.
* check for function exists.
* Moving changes to `/lib` folder because none of the changes are backwards compat specific.
Having this extension permanently in Gutenberg means that theme.json exporting will always use the latest version of the Theme JSON family of classes.
* Add to version control would help
* Added i18n domain
Co-authored-by: ramonjd
Co-authored-by: andrewserong
---
lib/block-template-utils.php | 114 ++++++++++++++++++
...-edit-site-export-controller-gutenberg.php | 46 +++++++
lib/load.php | 2 +
lib/rest-api.php | 12 ++
4 files changed, 174 insertions(+)
create mode 100644 lib/block-template-utils.php
create mode 100644 lib/class-wp-rest-edit-site-export-controller-gutenberg.php
diff --git a/lib/block-template-utils.php b/lib/block-template-utils.php
new file mode 100644
index 0000000000000..a644047d3cfdc
--- /dev/null
+++ b/lib/block-template-utils.php
@@ -0,0 +1,114 @@
+open( $filename, ZipArchive::CREATE | ZipArchive::OVERWRITE ) ) {
+ return new WP_Error( 'unable_to_create_zip', __( 'Unable to open export file (archive) for writing.', 'gutenberg' ) );
+ }
+
+ $zip->addEmptyDir( 'templates' );
+ $zip->addEmptyDir( 'parts' );
+
+ // Get path of the theme.
+ $theme_path = wp_normalize_path( get_stylesheet_directory() );
+
+ // Create recursive directory iterator.
+ $theme_files = new RecursiveIteratorIterator(
+ new RecursiveDirectoryIterator( $theme_path ),
+ RecursiveIteratorIterator::LEAVES_ONLY
+ );
+
+ // Make a copy of the current theme.
+ foreach ( $theme_files as $file ) {
+ // Skip directories as they are added automatically.
+ if ( ! $file->isDir() ) {
+ // Get real and relative path for current file.
+ $file_path = wp_normalize_path( $file );
+ $relative_path = substr( $file_path, strlen( $theme_path ) + 1 );
+
+ if ( ! wp_is_theme_directory_ignored( $relative_path ) ) {
+ $zip->addFile( $file_path, $relative_path );
+ }
+ }
+ }
+
+ // Load templates into the zip file.
+ $templates = gutenberg_get_block_templates();
+ foreach ( $templates as $template ) {
+ $template->content = traverse_and_serialize_blocks(
+ parse_blocks( $template->content ),
+ '_remove_theme_attribute_from_template_part_block'
+ );
+
+ $zip->addFromString(
+ 'templates/' . $template->slug . '.html',
+ $template->content
+ );
+ }
+
+ // Load template parts into the zip file.
+ $template_parts = gutenberg_get_block_templates( array(), 'wp_template_part' );
+ foreach ( $template_parts as $template_part ) {
+ $zip->addFromString(
+ 'parts/' . $template_part->slug . '.html',
+ $template_part->content
+ );
+ }
+
+ // Load theme.json into the zip file.
+ $tree = WP_Theme_JSON_Resolver_Gutenberg::get_theme_data( array(), array( 'with_supports' => false ) );
+ // Merge with user data.
+ $tree->merge( WP_Theme_JSON_Resolver_Gutenberg::get_user_data() );
+
+ $theme_json_raw = $tree->get_data();
+ // If a version is defined, add a schema.
+ if ( $theme_json_raw['version'] ) {
+ $theme_json_version = 'wp/' . substr( $wp_version, 0, 3 );
+ $schema = array( '$schema' => 'https://schemas.wp.org/' . $theme_json_version . '/theme.json' );
+ $theme_json_raw = array_merge( $schema, $theme_json_raw );
+ }
+
+ // Convert to a string.
+ $theme_json_encoded = wp_json_encode( $theme_json_raw, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE );
+
+ // Replace 4 spaces with a tab.
+ $theme_json_tabbed = preg_replace( '~(?:^|\G)\h{4}~m', "\t", $theme_json_encoded );
+
+ // Add the theme.json file to the zip.
+ $zip->addFromString(
+ 'theme.json',
+ $theme_json_tabbed
+ );
+
+ // Save changes to the zip file.
+ $zip->close();
+
+ return $filename;
+}
diff --git a/lib/class-wp-rest-edit-site-export-controller-gutenberg.php b/lib/class-wp-rest-edit-site-export-controller-gutenberg.php
new file mode 100644
index 0000000000000..b05de230dd0cc
--- /dev/null
+++ b/lib/class-wp-rest-edit-site-export-controller-gutenberg.php
@@ -0,0 +1,46 @@
+add_data( array( 'status' => 500 ) );
+
+ return $filename;
+ }
+
+ $theme_name = basename( get_stylesheet() );
+ header( 'Content-Type: application/zip' );
+ header( 'Content-Disposition: attachment; filename=' . $theme_name . '.zip' );
+ header( 'Content-Length: ' . filesize( $filename ) );
+ flush();
+ readfile( $filename );
+ unlink( $filename );
+ exit;
+ }
+}
diff --git a/lib/load.php b/lib/load.php
index 23985f9c8a92e..1f63c816f8173 100644
--- a/lib/load.php
+++ b/lib/load.php
@@ -53,6 +53,7 @@ function gutenberg_is_experiment_enabled( $name ) {
// Plugin specific code.
require_once __DIR__ . '/class-wp-rest-global-styles-controller-gutenberg.php';
+ require_once __DIR__ . '/class-wp-rest-edit-site-export-controller-gutenberg.php';
require_once __DIR__ . '/rest-api.php';
// Experimental.
@@ -206,6 +207,7 @@ function gutenberg_is_experiment_enabled( $name ) {
require __DIR__ . '/demo.php';
require __DIR__ . '/experiments-page.php';
require __DIR__ . '/interactivity-api.php';
+require __DIR__ . '/block-template-utils.php';
if ( gutenberg_is_experiment_enabled( 'gutenberg-full-page-client-side-navigation' ) ) {
require __DIR__ . '/experimental/full-page-client-side-navigation.php';
}
diff --git a/lib/rest-api.php b/lib/rest-api.php
index 04f521d132c46..fedd75151584d 100644
--- a/lib/rest-api.php
+++ b/lib/rest-api.php
@@ -18,3 +18,15 @@ function gutenberg_register_global_styles_endpoints() {
$global_styles_controller->register_routes();
}
add_action( 'rest_api_init', 'gutenberg_register_global_styles_endpoints' );
+
+if ( ! function_exists( 'gutenberg_register_edit_site_export_controller_endpoints' ) ) {
+ /**
+ * Registers the Edit Site Export REST API routes.
+ */
+ function gutenberg_register_edit_site_export_controller_endpoints() {
+ $edit_site_export_controller = new WP_REST_Edit_Site_Export_Controller_Gutenberg();
+ $edit_site_export_controller->register_routes();
+ }
+}
+
+add_action( 'rest_api_init', 'gutenberg_register_edit_site_export_controller_endpoints' );
From 6c063c44bac358b41dbf7b1e615ba40fb088f5eb Mon Sep 17 00:00:00 2001
From: Ramon
Date: Tue, 4 Jun 2024 10:09:57 +1000
Subject: [PATCH 05/17] Checking for preview mode (another way of saying
canvasMode === 'view', or the editor view is not currently editable) when
rendering the editor canvas container slot is a regression. Removing.
(#62212)
Co-authored-by: ramonjd
Co-authored-by: t-hamano
Co-authored-by: youknowriad
---
packages/editor/src/components/editor-interface/index.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/packages/editor/src/components/editor-interface/index.js b/packages/editor/src/components/editor-interface/index.js
index b78e3caa0b57c..386214189cfda 100644
--- a/packages/editor/src/components/editor-interface/index.js
+++ b/packages/editor/src/components/editor-interface/index.js
@@ -160,7 +160,7 @@ export default function EditorInterface( {
{ ( [ editorCanvasView ] ) =>
- ! isPreviewMode && editorCanvasView ? (
+ editorCanvasView ? (
editorCanvasView
) : (
<>
From ace8835357be3e23f17f5e723c86a5263d1c971a Mon Sep 17 00:00:00 2001
From: Ramon
Date: Tue, 4 Jun 2024 10:25:08 +1000
Subject: [PATCH 06/17] Syncing changes from Core
https://core.trac.wordpress.org/ticket/61021 for 6.6 compat (#62211)
Co-authored-by: ramonjd
Co-authored-by: andrewserong
---
lib/compat/wordpress-6.6/rest-api.php | 70 +++++++++++++++++++++++++++
1 file changed, 70 insertions(+)
diff --git a/lib/compat/wordpress-6.6/rest-api.php b/lib/compat/wordpress-6.6/rest-api.php
index 54796685f45ab..2cf026cc817c1 100644
--- a/lib/compat/wordpress-6.6/rest-api.php
+++ b/lib/compat/wordpress-6.6/rest-api.php
@@ -87,3 +87,73 @@ function gutenberg_register_global_styles_revisions_endpoints() {
}
add_action( 'rest_api_init', 'gutenberg_register_global_styles_revisions_endpoints' );
+
+if ( ! function_exists( 'gutenberg_register_wp_rest_themes_stylesheet_directory_uri_field' ) ) {
+ /**
+ * Adds `stylesheet_uri` fields to WP_REST_Themes_Controller class.
+ */
+ function gutenberg_register_wp_rest_themes_stylesheet_directory_uri_field() {
+ register_rest_field(
+ 'theme',
+ 'stylesheet_uri',
+ array(
+ 'get_callback' => function ( $item ) {
+ if ( ! empty( $item['stylesheet'] ) ) {
+ $theme = wp_get_theme( $item['stylesheet'] );
+ $current_theme = wp_get_theme();
+ if ( $theme->get_stylesheet() === $current_theme->get_stylesheet() ) {
+ return get_stylesheet_directory_uri();
+ } else {
+ return $theme->get_stylesheet_directory_uri();
+ }
+ }
+
+ return null;
+ },
+ 'schema' => array(
+ 'type' => 'string',
+ 'description' => __( 'The uri for the theme\'s stylesheet directory.', 'gutenberg' ),
+ 'format' => 'uri',
+ 'readonly' => true,
+ 'context' => array( 'view', 'edit', 'embed' ),
+ ),
+ )
+ );
+ }
+}
+add_action( 'rest_api_init', 'gutenberg_register_wp_rest_themes_stylesheet_directory_uri_field' );
+
+if ( ! function_exists( 'gutenberg_register_wp_rest_themes_template_directory_uri_field' ) ) {
+ /**
+ * Adds `template_uri` fields to WP_REST_Themes_Controller class.
+ */
+ function gutenberg_register_wp_rest_themes_template_directory_uri_field() {
+ register_rest_field(
+ 'theme',
+ 'template_uri',
+ array(
+ 'get_callback' => function ( $item ) {
+ if ( ! empty( $item['stylesheet'] ) ) {
+ $theme = wp_get_theme( $item['stylesheet'] );
+ $current_theme = wp_get_theme();
+ if ( $theme->get_stylesheet() === $current_theme->get_stylesheet() ) {
+ return get_template_directory_uri();
+ } else {
+ return $theme->get_template_directory_uri();
+ }
+ }
+
+ return null;
+ },
+ 'schema' => array(
+ 'type' => 'string',
+ 'description' => __( 'The uri for the theme\'s template directory. If this is a child theme, this refers to the parent theme, otherwise this is the same as the theme\'s stylesheet directory.', 'gutenberg' ),
+ 'format' => 'uri',
+ 'readonly' => true,
+ 'context' => array( 'view', 'edit', 'embed' ),
+ ),
+ )
+ );
+ }
+}
+add_action( 'rest_api_init', 'gutenberg_register_wp_rest_themes_template_directory_uri_field' );
From bbf0816cc36409b84df0710f022ce4e28c66a1cc Mon Sep 17 00:00:00 2001
From: Jon Surrell
Date: Tue, 4 Jun 2024 07:41:45 +0200
Subject: [PATCH 07/17] Script Modules: Adjust data filter name and script tag
ID (#62170)
Update the Script Module data filter name and script tag ID to align with Core changes.
See https://github.com/WordPress/wordpress-develop/pull/6682.
Co-authored-by: sirreal
Co-authored-by: gziolo
---
lib/experimental/script-modules.php | 10 +++++-----
packages/interactivity/src/store.ts | 4 +++-
2 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/lib/experimental/script-modules.php b/lib/experimental/script-modules.php
index a9d5540e56dc5..709ab322f63a3 100644
--- a/lib/experimental/script-modules.php
+++ b/lib/experimental/script-modules.php
@@ -205,10 +205,10 @@ function gutenberg_dequeue_module( $module_identifier ) {
* This embeds data in the page HTML so that it is available on page load.
*
* Data can be associated with a given Script Module by using the
- * `scriptmoduledata_{$module_id}` filter.
+ * `script_module_data_{$module_id}` filter.
*
* The data for a given Script Module will be JSON serialized in a script tag with an ID
- * like `wp-scriptmodule-data_{$module_id}`.
+ * like `wp-script-module-data-{$module_id}`.
*/
function gutenberg_print_script_module_data(): void {
$get_marked_for_enqueue = new ReflectionMethod( 'WP_Script_Modules', 'get_marked_for_enqueue' );
@@ -236,14 +236,14 @@ function gutenberg_print_script_module_data(): void {
* If the filter returns no data (an empty array), nothing will be embedded in the page.
*
* The data for a given Script Module, if provided, will be JSON serialized in a script tag
- * with an ID like `wp-scriptmodule-data_{$module_id}`.
+ * with an ID like `wp-script-module-data-{$module_id}`.
*
* The dynamic portion of the hook name, `$module_id`, refers to the Script Module ID that
* the data is associated with.
*
* @param array $data The data that should be associated with the array.
*/
- $data = apply_filters( "scriptmoduledata_{$module_id}", array() );
+ $data = apply_filters( "script_module_data_{$module_id}", array() );
if ( is_array( $data ) && ! empty( $data ) ) {
/*
@@ -281,7 +281,7 @@ function gutenberg_print_script_module_data(): void {
wp_json_encode( $data, $json_encode_flags ),
array(
'type' => 'application/json',
- 'id' => "wp-scriptmodule-data_{$module_id}",
+ 'id' => "wp-script-module-data-{$module_id}",
)
);
}
diff --git a/packages/interactivity/src/store.ts b/packages/interactivity/src/store.ts
index f6366283d2d6a..281a6c266021e 100644
--- a/packages/interactivity/src/store.ts
+++ b/packages/interactivity/src/store.ts
@@ -321,7 +321,9 @@ export function store(
export const parseInitialData = ( dom = document ) => {
const jsonDataScriptTag =
// Preferred Script Module data passing form
- dom.getElementById( 'wp-scriptmodule-data_@wordpress/interactivity' ) ??
+ dom.getElementById(
+ 'wp-script-module-data-@wordpress/interactivity'
+ ) ??
// Legacy form
dom.getElementById( 'wp-interactivity-data' );
if ( jsonDataScriptTag?.textContent ) {
From dbf201449e9736f672b61e422787d47659db327a Mon Sep 17 00:00:00 2001
From: Joen A <1204802+jasmussen@users.noreply.github.com>
Date: Tue, 4 Jun 2024 09:55:29 +0200
Subject: [PATCH 08/17] Update URL to uppercase. (#62231)
---
.../src/components/link-control/search-input.js | 2 +-
test/e2e/specs/editor/blocks/links.spec.js | 6 +++---
test/e2e/specs/editor/various/block-bindings.spec.js | 4 ++--
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/packages/block-editor/src/components/link-control/search-input.js b/packages/block-editor/src/components/link-control/search-input.js
index 238b2d6b3acc7..78730463389e2 100644
--- a/packages/block-editor/src/components/link-control/search-input.js
+++ b/packages/block-editor/src/components/link-control/search-input.js
@@ -125,7 +125,7 @@ const LinkControlSearchInput = forwardRef(
className={ className }
value={ value }
onChange={ onInputChange }
- placeholder={ placeholder ?? __( 'Search or type url' ) }
+ placeholder={ placeholder ?? __( 'Search or type URL' ) }
__experimentalRenderSuggestions={
showSuggestions ? handleRenderSuggestions : null
}
diff --git a/test/e2e/specs/editor/blocks/links.spec.js b/test/e2e/specs/editor/blocks/links.spec.js
index 5686eaed0c83e..02400fe9c9dd8 100644
--- a/test/e2e/specs/editor/blocks/links.spec.js
+++ b/test/e2e/specs/editor/blocks/links.spec.js
@@ -235,7 +235,7 @@ test.describe( 'Links', () => {
// Change the URL.
// getByPlaceholder required in order to handle Link Control component
// managing focus onto other inputs within the control.
- await page.getByPlaceholder( 'Search or type url' ).fill( '' );
+ await page.getByPlaceholder( 'Search or type URL' ).fill( '' );
await page.keyboard.type( '/handbook' );
// Submit the link.
@@ -349,7 +349,7 @@ test.describe( 'Links', () => {
// Change the URL.
// getByPlaceholder required in order to handle Link Control component
// managing focus onto other inputs within the control.
- await page.getByPlaceholder( 'Search or type url' ).fill( '' );
+ await page.getByPlaceholder( 'Search or type URL' ).fill( '' );
await page.keyboard.type( '/handbook' );
// Submit the link.
@@ -679,7 +679,7 @@ test.describe( 'Links', () => {
// Change the URL.
// Note: getByPlaceholder required in order to handle Link Control component
// managing focus onto other inputs within the control.
- await linkPopover.getByPlaceholder( 'Search or type url' ).fill( '' );
+ await linkPopover.getByPlaceholder( 'Search or type URL' ).fill( '' );
await page.keyboard.type( 'wordpress.org' );
// Save the link.
diff --git a/test/e2e/specs/editor/various/block-bindings.spec.js b/test/e2e/specs/editor/various/block-bindings.spec.js
index 87e5b2f2e10b1..be5c7594b46da 100644
--- a/test/e2e/specs/editor/various/block-bindings.spec.js
+++ b/test/e2e/specs/editor/various/block-bindings.spec.js
@@ -2044,7 +2044,7 @@ test.describe( 'Block bindings', () => {
.getByRole( 'button', { name: 'Edit link', exact: true } )
.click();
await page
- .getByPlaceholder( 'Search or type url' )
+ .getByPlaceholder( 'Search or type URL' )
.fill( '#url-custom-field-modified' );
await pageUtils.pressKeys( 'Enter' );
@@ -2103,7 +2103,7 @@ test.describe( 'Block bindings', () => {
.getByRole( 'button', { name: 'Edit link', exact: true } )
.click();
await page
- .getByPlaceholder( 'Search or type url' )
+ .getByPlaceholder( 'Search or type URL' )
.fill( imageCustomFieldSrc );
await pageUtils.pressKeys( 'Enter' );
From fd7becb30991469b0dc7784be4ca5796a4dcd9f9 Mon Sep 17 00:00:00 2001
From: James Koster
Date: Tue, 4 Jun 2024 10:07:23 +0100
Subject: [PATCH 09/17] Update sidebar title + icon + site title alignment
(#62191)
* Update sidebar title + icon alignement
* Fix alignment between sidebar title and site title
* revert alignment, adjust padding
Co-authored-by: jameskoster
Co-authored-by: richtabor
Co-authored-by: t-hamano
---
.../edit-site/src/components/sidebar-navigation-screen/index.js | 2 +-
.../src/components/sidebar-navigation-screen/style.scss | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/packages/edit-site/src/components/sidebar-navigation-screen/index.js b/packages/edit-site/src/components/sidebar-navigation-screen/index.js
index 19e3335f9ff06..417e643bb8b04 100644
--- a/packages/edit-site/src/components/sidebar-navigation-screen/index.js
+++ b/packages/edit-site/src/components/sidebar-navigation-screen/index.js
@@ -76,7 +76,7 @@ export default function SidebarNavigationScreen( {
justify="flex-start"
>
diff --git a/packages/edit-site/src/components/sidebar-navigation-screen/style.scss b/packages/edit-site/src/components/sidebar-navigation-screen/style.scss
index bf6b79d151d59..7691f9ba2cdb0 100644
--- a/packages/edit-site/src/components/sidebar-navigation-screen/style.scss
+++ b/packages/edit-site/src/components/sidebar-navigation-screen/style.scss
@@ -67,8 +67,8 @@
.edit-site-sidebar-navigation-screen__title {
flex-grow: 1;
- padding: $grid-unit-15 * 0.5 0 0 0;
overflow-wrap: break-word;
+ padding: $grid-unit-05 * 0.5 0 0 0;
}
.edit-site-sidebar-navigation-screen__actions {
From 5e51181b8e4cac362daa14a5ac53cf73f2cd16ad Mon Sep 17 00:00:00 2001
From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com>
Date: Tue, 4 Jun 2024 12:01:59 +0200
Subject: [PATCH 10/17] Remove unused `syncDerivedUpdates` action (#62229)
* Remove `syncDerivedUpdates` function
* Remove `syncDerivedUpdates` mention
* Remove unused `undoIgnoreBlocks`
---
.../src/components/provider/use-block-sync.js | 6 ----
.../block-editor/src/store/private-actions.js | 29 -------------------
.../block-editor/src/store/undo-ignore.js | 4 ---
3 files changed, 39 deletions(-)
delete mode 100644 packages/block-editor/src/store/undo-ignore.js
diff --git a/packages/block-editor/src/components/provider/use-block-sync.js b/packages/block-editor/src/components/provider/use-block-sync.js
index 300c108a70cf1..4e9cc9784554f 100644
--- a/packages/block-editor/src/components/provider/use-block-sync.js
+++ b/packages/block-editor/src/components/provider/use-block-sync.js
@@ -9,7 +9,6 @@ import { cloneBlock } from '@wordpress/blocks';
* Internal dependencies
*/
import { store as blockEditorStore } from '../../store';
-import { undoIgnoreBlocks } from '../../store/undo-ignore';
const noop = () => {};
@@ -274,10 +273,6 @@ export default function useBlockSync( {
const updateParent = isPersistent
? onChangeRef.current
: onInputRef.current;
- const undoIgnore = undoIgnoreBlocks.has( blocks );
- if ( undoIgnore ) {
- undoIgnoreBlocks.delete( blocks );
- }
updateParent( blocks, {
selection: {
selectionStart: getSelectionStart(),
@@ -285,7 +280,6 @@ export default function useBlockSync( {
initialPosition:
getSelectedBlocksInitialCaretPosition(),
},
- undoIgnore,
} );
}
previousAreBlocksDifferent = areBlocksDifferent;
diff --git a/packages/block-editor/src/store/private-actions.js b/packages/block-editor/src/store/private-actions.js
index 28a7b1da98f73..5e4e0c7a222b0 100644
--- a/packages/block-editor/src/store/private-actions.js
+++ b/packages/block-editor/src/store/private-actions.js
@@ -6,7 +6,6 @@ import { Platform } from '@wordpress/element';
/**
* Internal dependencies
*/
-import { undoIgnoreBlocks } from './undo-ignore';
import { store as blockEditorStore } from './index';
import { unlock } from '../lock-unlock';
@@ -292,34 +291,6 @@ export function deleteStyleOverride( id ) {
};
}
-/**
- * A higher-order action that mark every change inside a callback as "non-persistent"
- * and ignore pushing to the undo history stack. It's primarily used for synchronized
- * derived updates from the block editor without affecting the undo history.
- *
- * @param {() => void} callback The synchronous callback to derive updates.
- */
-export function syncDerivedUpdates( callback ) {
- return ( { dispatch, select, registry } ) => {
- registry.batch( () => {
- // Mark every change in the `callback` as non-persistent.
- dispatch( {
- type: 'SET_EXPLICIT_PERSISTENT',
- isPersistentChange: false,
- } );
- callback();
- dispatch( {
- type: 'SET_EXPLICIT_PERSISTENT',
- isPersistentChange: undefined,
- } );
-
- // Ignore pushing undo stack for the updated blocks.
- const updatedBlocks = select.getBlocks();
- undoIgnoreBlocks.add( updatedBlocks );
- } );
- };
-}
-
/**
* Action that sets the element that had focus when focus leaves the editor canvas.
*
diff --git a/packages/block-editor/src/store/undo-ignore.js b/packages/block-editor/src/store/undo-ignore.js
deleted file mode 100644
index f0a64428ea7c2..0000000000000
--- a/packages/block-editor/src/store/undo-ignore.js
+++ /dev/null
@@ -1,4 +0,0 @@
-// Keep track of the blocks that should not be pushing an additional
-// undo stack when editing the entity.
-// See the implementation of `syncDerivedUpdates` and `useBlockSync`.
-export const undoIgnoreBlocks = new WeakSet();
From 503bd62fce6a60449b2d15cf8ae83110ac396316 Mon Sep 17 00:00:00 2001
From: Gerardo Pacheco
Date: Tue, 4 Jun 2024 12:12:41 +0200
Subject: [PATCH 11/17] [Mobile] - Unsupported block - UI improvements (#62240)
* Mobile - Unsupported block editor - Update editor style overrides
* Mobile - Unsupported block - Update UI to show Tap to edit for unsupported blocks, simplifying the flow to open the Unsupported block editor
* Fix unsupported block condition
* Update snapshot
* Fix condition for the help icon
---
.../block-library/src/missing/edit.native.js | 50 +++++--
.../test/__snapshots__/edit.native.js.snap | 136 ++++++++++--------
.../editor-style-overrides.css | 27 +++-
3 files changed, 141 insertions(+), 72 deletions(-)
diff --git a/packages/block-library/src/missing/edit.native.js b/packages/block-library/src/missing/edit.native.js
index 7432f5fae0f12..950d9afaaebf3 100644
--- a/packages/block-library/src/missing/edit.native.js
+++ b/packages/block-library/src/missing/edit.native.js
@@ -1,12 +1,7 @@
/**
* External dependencies
*/
-import {
- View,
- Text,
- TouchableWithoutFeedback,
- TouchableOpacity,
-} from 'react-native';
+import { View, Text, TouchableOpacity } from 'react-native';
/**
* WordPress dependencies
@@ -25,6 +20,7 @@ import {
store as blockEditorStore,
} from '@wordpress/block-editor';
import { store as noticesStore } from '@wordpress/notices';
+import { requestUnsupportedBlockFallback } from '@wordpress/react-native-bridge';
/**
* Internal dependencies
@@ -48,11 +44,38 @@ export class UnsupportedBlockEdit extends Component {
}
toggleSheet() {
+ const { attributes, block, clientId } = this.props;
+ const { originalName } = attributes;
+ const title = this.getTitle();
+ const blockContent = serialize( block ? [ block ] : [] );
+
+ if ( this.canEditUnsupportedBlock() ) {
+ requestUnsupportedBlockFallback(
+ blockContent,
+ clientId,
+ originalName,
+ title
+ );
+ return;
+ }
+
this.setState( {
showHelp: ! this.state.showHelp,
} );
}
+ canEditUnsupportedBlock() {
+ const {
+ canEnableUnsupportedBlockEditor,
+ isUnsupportedBlockEditorSupported,
+ } = this.props;
+
+ return (
+ ! canEnableUnsupportedBlockEditor &&
+ isUnsupportedBlockEditorSupported
+ );
+ }
+
closeSheet() {
this.setState( {
showHelp: false,
@@ -186,7 +209,11 @@ export class UnsupportedBlockEdit extends Component {
);
const subtitle = (
- { __( 'Unsupported' ) }
+
+ { this.canEditUnsupportedBlock()
+ ? __( 'Tap to edit' )
+ : __( 'Unsupported' ) }
+
);
const icon = blockType
@@ -198,8 +225,8 @@ export class UnsupportedBlockEdit extends Component {
);
const iconClassName = 'unsupported-icon' + '-' + preferredColorScheme;
return (
-
- { this.renderHelpIcon() }
+ { ! this.canEditUnsupportedBlock() &&
+ this.renderHelpIcon() }
-
+
);
}
}
diff --git a/packages/block-library/src/missing/test/__snapshots__/edit.native.js.snap b/packages/block-library/src/missing/test/__snapshots__/edit.native.js.snap
index 245410a5c5d57..2ac371120be4b 100644
--- a/packages/block-library/src/missing/test/__snapshots__/edit.native.js.snap
+++ b/packages/block-library/src/missing/test/__snapshots__/edit.native.js.snap
@@ -9,12 +9,21 @@ exports[`Missing block renders without crashing 1`] = `
{
"busy": undefined,
"checked": undefined,
- "disabled": true,
+ "disabled": undefined,
"expanded": undefined,
"selected": undefined,
}
}
+ accessibilityValue={
+ {
+ "max": undefined,
+ "min": undefined,
+ "now": undefined,
+ "text": undefined,
+ }
+ }
accessible={true}
+ collapsable={false}
focusable={true}
onClick={[Function]}
onResponderGrant={[Function]}
@@ -23,72 +32,79 @@ exports[`Missing block renders without crashing 1`] = `
onResponderTerminate={[Function]}
onResponderTerminationRequest={[Function]}
onStartShouldSetResponder={[Function]}
+ style={
+ {
+ "opacity": 1,
+ }
+ }
>
-
+
-
-
-
-
+
+
+
+
+
+ missing/block/title
+
+
- missing/block/title
+ Unsupported
-
- Unsupported
-
`;
diff --git a/packages/react-native-bridge/common/gutenberg-web-single-block/editor-style-overrides.css b/packages/react-native-bridge/common/gutenberg-web-single-block/editor-style-overrides.css
index 484cdfebfbd9b..46782e944d0c3 100644
--- a/packages/react-native-bridge/common/gutenberg-web-single-block/editor-style-overrides.css
+++ b/packages/react-native-bridge/common/gutenberg-web-single-block/editor-style-overrides.css
@@ -3,8 +3,28 @@
display: none;
}
+/* Remove header toolbar */
+.editor-header__toolbar {
+ display: none;
+}
+
+/* Hide all children of editor-header__settings */
+.editor-header__settings > * {
+ display: none;
+}
+
+/* Show only the interface-pinned-items container */
+.editor-header__settings > .interface-pinned-items {
+ display: block;
+}
+
+.components-button.editor-post-publish-panel__toggle.is-primary{
+ display: none;
+}
+
/* Remove default block appender at the end of the post */
-.block-list-appender {
+.block-list-appender, .block-list-appender__toggle,
+.block-editor-inserter, .components-autocomplete__popover {
display: none;
}
@@ -18,6 +38,11 @@
display: none;
}
+/* Remove block inserter popover */
+.block-editor-block-popover {
+ display: none;
+}
+
/* Right align post header children as we will only display one child */
.edit-post-header {
justify-content: flex-end;
From c5950d355ed02b88326d89126eab103148016549 Mon Sep 17 00:00:00 2001
From: Jorge Costa
Date: Tue, 4 Jun 2024 11:15:26 +0100
Subject: [PATCH 12/17] Update: Block styles documentation.
---
docs/reference-guides/block-api/block-styles.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/reference-guides/block-api/block-styles.md b/docs/reference-guides/block-api/block-styles.md
index 90b6c06d18f59..b47b1a76a71f6 100644
--- a/docs/reference-guides/block-api/block-styles.md
+++ b/docs/reference-guides/block-api/block-styles.md
@@ -1,6 +1,6 @@
# Styles
-Block Styles allow alternative styles to be applied to existing blocks. They work by adding a className to the block's wrapper. This className can be used to provide an alternative styling for the block if the block style is selected. See the [Getting Started with JavaScript tutorial](/docs/how-to-guides/javascript/) for a full example.
+Block Styles allow alternative styles to be applied to existing blocks. They work by adding a className to the block's wrapper. This className can be used to provide an alternative styling for the block if the block style is selected. See the [Use styles and stylesheets](/docs/how-to-guides/block-tutorial/applying-styles-with-stylesheets.md) for a full example on how to apply styles to a block.
_Example:_
From b89e79aa324d6ea857e2ad2738b5a4b8a6868f29 Mon Sep 17 00:00:00 2001
From: Gerardo Pacheco
Date: Tue, 4 Jun 2024 12:29:10 +0200
Subject: [PATCH 13/17] [Mobile] - Image corrector - Check the path extension
is a valid one (#62190)
* Mobile - Image corrector - Check the path extension is a valid one
* [Mobile] - Image corrector- Expand comment explaining the filtering for file: media paths
* Integration Test helpers - Expand pasteIntoRichText to support passing files as a parameter
* Mobile Editor Tests - Add new tests related to pasting HTML content with local image paths
* Update snapshot
---
.../raw-handling/image-corrector.native.js | 5 ++-
.../test/__snapshots__/editor.native.js.snap | 12 +++++++
packages/edit-post/src/test/editor.native.js | 34 +++++++++++++++++++
.../rich-text-paste.js | 13 +++----
4 files changed, 57 insertions(+), 7 deletions(-)
diff --git a/packages/blocks/src/api/raw-handling/image-corrector.native.js b/packages/blocks/src/api/raw-handling/image-corrector.native.js
index c6a9288ede2d3..550c2e0e6e153 100644
--- a/packages/blocks/src/api/raw-handling/image-corrector.native.js
+++ b/packages/blocks/src/api/raw-handling/image-corrector.native.js
@@ -10,7 +10,10 @@ export default function imageCorrector( node ) {
return;
}
- if ( node.src.indexOf( 'file:' ) === 0 ) {
+ // For local files makes sure the path doesn't end with an invalid extension.
+ // This scenario often happens with content from MS Word and similar text apps.
+ // We still need to support local files pasted from the users Media library.
+ if ( node.src.startsWith( 'file:' ) && node.src.slice( -1 ) === '/' ) {
node.setAttribute( 'src', '' );
}
diff --git a/packages/edit-post/src/test/__snapshots__/editor.native.js.snap b/packages/edit-post/src/test/__snapshots__/editor.native.js.snap
index 76bb42d5a2cce..4a88b249a1db6 100644
--- a/packages/edit-post/src/test/__snapshots__/editor.native.js.snap
+++ b/packages/edit-post/src/test/__snapshots__/editor.native.js.snap
@@ -1,5 +1,17 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
+exports[`Editor adds empty image block when pasting unsupported HTML local image path 1`] = `
+"
+
+"
+`;
+
+exports[`Editor adds image block when pasting HTML local image path 1`] = `
+"
+
+"
+`;
+
exports[`Editor appends media correctly for allowed types 1`] = `
"
diff --git a/packages/edit-post/src/test/editor.native.js b/packages/edit-post/src/test/editor.native.js
index acafc4d68d42a..8fe116758608b 100644
--- a/packages/edit-post/src/test/editor.native.js
+++ b/packages/edit-post/src/test/editor.native.js
@@ -9,8 +9,10 @@ import {
getEditorHtml,
getEditorTitle,
initializeEditor,
+ pasteIntoRichText,
screen,
setupCoreBlocks,
+ within,
} from 'test/helpers';
import { BackHandler } from 'react-native';
@@ -98,6 +100,38 @@ describe( 'Editor', () => {
} );
} );
+ it( 'adds empty image block when pasting unsupported HTML local image path', async () => {
+ await initializeEditor();
+ await addBlock( screen, 'Paragraph' );
+
+ const paragraphBlock = getBlock( screen, 'Paragraph' );
+ fireEvent.press( paragraphBlock );
+ const paragraphTextInput =
+ within( paragraphBlock ).getByPlaceholderText( 'Start writing…' );
+
+ pasteIntoRichText( paragraphTextInput, {
+ text: '
',
+ } );
+
+ expect( getEditorHtml() ).toMatchSnapshot();
+ } );
+
+ it( 'adds image block when pasting HTML local image path', async () => {
+ await initializeEditor();
+ await addBlock( screen, 'Paragraph' );
+
+ const paragraphBlock = getBlock( screen, 'Paragraph' );
+ fireEvent.press( paragraphBlock );
+ const paragraphTextInput =
+ within( paragraphBlock ).getByPlaceholderText( 'Start writing…' );
+
+ pasteIntoRichText( paragraphTextInput, {
+ files: [ 'file:///path/to/file.png' ],
+ } );
+
+ expect( getEditorHtml() ).toMatchSnapshot();
+ } );
+
it( 'appends media correctly for allowed types', async () => {
// Arrange
requestMediaImport
diff --git a/test/native/integration-test-helpers/rich-text-paste.js b/test/native/integration-test-helpers/rich-text-paste.js
index d2c01ed2fb5a7..6d447181e0b8d 100644
--- a/test/native/integration-test-helpers/rich-text-paste.js
+++ b/test/native/integration-test-helpers/rich-text-paste.js
@@ -6,19 +6,20 @@ import { fireEvent } from '@testing-library/react-native';
/**
* Paste content into a RichText component.
*
- * @param {import('react-test-renderer').ReactTestInstance} richText RichText test instance.
- * @param {Object} content Content to paste.
- * @param {string} content.text Text format of the content.
- * @param {string} [content.html] HTML format of the content. If not provided, text format will be used.
+ * @param {import('react-test-renderer').ReactTestInstance} richText RichText test instance.
+ * @param {Object} content Content to paste.
+ * @param {string} content.text Text format of the content.
+ * @param {string} [content.html] HTML format of the content. If not provided, text format will be used.
+ * @param {string} [content.files] Files array to add to the editor.
*/
-export const pasteIntoRichText = ( richText, { text, html } ) => {
+export const pasteIntoRichText = ( richText, { text, html, files = [] } ) => {
fireEvent( richText, 'focus' );
fireEvent( richText, 'paste', {
preventDefault: jest.fn(),
nativeEvent: {
eventCount: 1,
target: undefined,
- files: [],
+ files,
pastedHtml: html || text,
pastedText: text,
},
From 2cd72c25e2834a6a00d2c0f4cb71cce23e8d4321 Mon Sep 17 00:00:00 2001
From: Joen A <1204802+jasmussen@users.noreply.github.com>
Date: Tue, 4 Jun 2024 12:45:39 +0200
Subject: [PATCH 14/17] Try: Fix mover positioning. (#62226)
* Try: Fix mover positioning.
* Update packages/editor/src/components/collapsible-block-toolbar/style.scss
Co-authored-by: Aki Hamano <54422211+t-hamano@users.noreply.github.com>
---------
Co-authored-by: Aki Hamano <54422211+t-hamano@users.noreply.github.com>
---
.../editor/src/components/collapsible-block-toolbar/style.scss | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/packages/editor/src/components/collapsible-block-toolbar/style.scss b/packages/editor/src/components/collapsible-block-toolbar/style.scss
index 701d6fa7c5ecc..80d25da1a3e28 100644
--- a/packages/editor/src/components/collapsible-block-toolbar/style.scss
+++ b/packages/editor/src/components/collapsible-block-toolbar/style.scss
@@ -64,8 +64,9 @@
// Move up a little to prevent the toolbar shift when focus is on the vertical movers.
@include break-small() {
&:not(.is-horizontal) .block-editor-block-mover__move-button-container {
+ height: $grid-unit-50;
position: relative;
- top: -10px;
+ top: -5px; // Should be -4px, but that causes scrolling when focus lands on the movers, in a 60px header.
}
}
}
From d93cea5edbc82980f28f13025b4af03e42e8db54 Mon Sep 17 00:00:00 2001
From: Jorge Costa
Date: Tue, 4 Jun 2024 12:56:11 +0200
Subject: [PATCH 15/17] Update: Slotfill documentation samples (links, code,
and rephrase). (#62271)
Co-authored-by: jorgefilipecosta
---
docs/reference-guides/slotfills/README.md | 88 ++++++++++++++++-------
1 file changed, 62 insertions(+), 26 deletions(-)
diff --git a/docs/reference-guides/slotfills/README.md b/docs/reference-guides/slotfills/README.md
index 043a50cb5186e..ea324f71b25e8 100644
--- a/docs/reference-guides/slotfills/README.md
+++ b/docs/reference-guides/slotfills/README.md
@@ -33,7 +33,7 @@ registerPlugin( 'post-status-info-test', { render: PluginPostStatusInfoTest } );
SlotFills are created using `createSlotFill`. This creates two components, `Slot` and `Fill` which are then used to create a new component that is exported on the `wp.plugins` global.
-**Definition of the `PluginPostStatusInfo` SlotFill** ([see core code](https://github.com/WordPress/gutenberg/blob/HEAD/packages/edit-post/src/components/sidebar/plugin-post-status-info/index.js#L54))
+**Definition of the `PluginPostStatusInfo` SlotFill** ([see core code](https://github.com/WordPress/gutenberg/blob/HEAD/packages/editor/src/components/plugin-post-status-info/index.js#L55))
```js
/**
@@ -61,34 +61,70 @@ export default PluginPostStatusInfo;
This new Slot is then exposed in the editor. The example below is from core and represents the Summary panel.
As we can see, the `` is wrapping all of the items that will appear in the panel.
-Any items that have been added via the SlotFill ( see the example above ), will be included in the `fills` parameter and be displayed between the `` and `` components.
+Any items that have been added via the SlotFill ( see the example above ), will be included in the `fills` parameter and be displayed in the end of the component.
-See [core code](https://github.com/WordPress/gutenberg/tree/HEAD/packages/edit-post/src/components/sidebar/post-status/index.js#L26).
+See [core code](https://github.com/WordPress/gutenberg/tree/HEAD/packages/editor/src/components/sidebar/post-summary.js#L39).
```js
-const PostStatus = ( { isOpened, onTogglePanel } ) => (
-
-
- { ( fills ) => (
- <>
-
-
-
-
-
-
- { fills }
-
- >
- ) }
-
-
-);
+export default function PostSummary( { onActionPerformed } ) {
+ const { isRemovedPostStatusPanel } = useSelect( ( select ) => {
+ // We use isEditorPanelRemoved to hide the panel if it was programatically removed. We do
+ // not use isEditorPanelEnabled since this panel should not be disabled through the UI.
+ const { isEditorPanelRemoved, getCurrentPostType } =
+ select( editorStore );
+ return {
+ isRemovedPostStatusPanel: isEditorPanelRemoved( PANEL_NAME ),
+ postType: getCurrentPostType(),
+ };
+ }, [] );
+
+ return (
+
+
+ { ( fills ) => (
+ <>
+
+
+ }
+ />
+
+
+
+
+
+
+ { ! isRemovedPostStatusPanel && (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ { fills }
+
+ ) }
+
+ >
+ ) }
+
+
+ );
+}
```
## Currently available SlotFills and examples
From 329369bd9925e7c2d1fd370ed07cb5fccddbf74d Mon Sep 17 00:00:00 2001
From: Joen A <1204802+jasmussen@users.noreply.github.com>
Date: Tue, 4 Jun 2024 13:25:58 +0200
Subject: [PATCH 16/17] Update instances of text-wrap: pretty to fall back to
balance (#62233)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* Update instances of text-wrap: pretty to fall back to balance
* fix update snapshots
* add changelog entry
---------
Co-authored-by: Fabian Kägy
---
packages/components/CHANGELOG.md | 4 ++++
.../dimension-control/test/__snapshots__/index.test.js.snap | 4 ++++
.../components/src/heading/test/__snapshots__/index.tsx.snap | 1 +
packages/components/src/text/styles.ts | 1 +
.../components/src/text/test/__snapshots__/index.tsx.snap | 2 ++
packages/editor/src/components/post-panel-row/style.scss | 1 +
packages/editor/src/components/post-publish-panel/style.scss | 1 +
7 files changed, 14 insertions(+)
diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md
index 4ad4dd4ec6312..e8d65cfd9ce83 100644
--- a/packages/components/CHANGELOG.md
+++ b/packages/components/CHANGELOG.md
@@ -2,6 +2,10 @@
## Unreleased
+### Enhancements
+
+- Add `text-wrap: balance` fallback to all instances of `text-wrap: pretty` for greater cross browser compatibility. ([#62233](https://github.com/WordPress/gutenberg/pull/62233))
+
## 28.0.0 (2024-05-31)
### Breaking Changes
diff --git a/packages/components/src/dimension-control/test/__snapshots__/index.test.js.snap b/packages/components/src/dimension-control/test/__snapshots__/index.test.js.snap
index 73c8ebcfb4927..608cadbcf544f 100644
--- a/packages/components/src/dimension-control/test/__snapshots__/index.test.js.snap
+++ b/packages/components/src/dimension-control/test/__snapshots__/index.test.js.snap
@@ -68,6 +68,7 @@ exports[`DimensionControl rendering renders with custom sizes 1`] = `
color: #1e1e1e;
line-height: 1.4;
margin: 0;
+ text-wrap: balance;
text-wrap: pretty;
font-size: calc((13 / 13) * 13px);
font-weight: normal;
@@ -347,6 +348,7 @@ exports[`DimensionControl rendering renders with defaults 1`] = `
color: #1e1e1e;
line-height: 1.4;
margin: 0;
+ text-wrap: balance;
text-wrap: pretty;
font-size: calc((13 / 13) * 13px);
font-weight: normal;
@@ -636,6 +638,7 @@ exports[`DimensionControl rendering renders with icon and custom icon label 1`]
color: #1e1e1e;
line-height: 1.4;
margin: 0;
+ text-wrap: balance;
text-wrap: pretty;
font-size: calc((13 / 13) * 13px);
font-weight: normal;
@@ -937,6 +940,7 @@ exports[`DimensionControl rendering renders with icon and default icon label 1`]
color: #1e1e1e;
line-height: 1.4;
margin: 0;
+ text-wrap: balance;
text-wrap: pretty;
font-size: calc((13 / 13) * 13px);
font-weight: normal;
diff --git a/packages/components/src/heading/test/__snapshots__/index.tsx.snap b/packages/components/src/heading/test/__snapshots__/index.tsx.snap
index 9a779613f56c2..cf863c4b2bb2e 100644
--- a/packages/components/src/heading/test/__snapshots__/index.tsx.snap
+++ b/packages/components/src/heading/test/__snapshots__/index.tsx.snap
@@ -5,6 +5,7 @@ exports[`props should render correctly 1`] = `
color: #1e1e1e;
line-height: 1.4;
margin: 0;
+ text-wrap: balance;
text-wrap: pretty;
color: #1e1e1e;
font-size: calc(1.95 * 13px);
diff --git a/packages/components/src/text/styles.ts b/packages/components/src/text/styles.ts
index 1a0a6383363df..c7d4855279593 100644
--- a/packages/components/src/text/styles.ts
+++ b/packages/components/src/text/styles.ts
@@ -12,6 +12,7 @@ export const Text = css`
color: ${ COLORS.gray[ 900 ] };
line-height: ${ CONFIG.fontLineHeightBase };
margin: 0;
+ text-wrap: balance; /* Fallback for Safari. */
text-wrap: pretty;
`;
diff --git a/packages/components/src/text/test/__snapshots__/index.tsx.snap b/packages/components/src/text/test/__snapshots__/index.tsx.snap
index d2caecd9bf059..1b98c0853ac54 100644
--- a/packages/components/src/text/test/__snapshots__/index.tsx.snap
+++ b/packages/components/src/text/test/__snapshots__/index.tsx.snap
@@ -22,6 +22,7 @@ exports[`Text should render highlighted words with highlightCaseSensitive 1`] =
color: #1e1e1e;
line-height: 1.4;
margin: 0;
+ text-wrap: balance;
text-wrap: pretty;
font-size: calc((13 / 13) * 13px);
font-weight: normal;
@@ -54,6 +55,7 @@ exports[`Text snapshot tests should render correctly 1`] = `
color: #1e1e1e;
line-height: 1.4;
margin: 0;
+ text-wrap: balance;
text-wrap: pretty;
font-size: calc((13 / 13) * 13px);
font-weight: normal;
diff --git a/packages/editor/src/components/post-panel-row/style.scss b/packages/editor/src/components/post-panel-row/style.scss
index baa7d7dd98977..024394c3aaf33 100644
--- a/packages/editor/src/components/post-panel-row/style.scss
+++ b/packages/editor/src/components/post-panel-row/style.scss
@@ -25,6 +25,7 @@
.components-button {
max-width: 100%;
text-align: left;
+ text-wrap: balance; // Fallback for Safari.
text-wrap: pretty;
height: auto;
min-height: $button-size-compact;
diff --git a/packages/editor/src/components/post-publish-panel/style.scss b/packages/editor/src/components/post-publish-panel/style.scss
index c0ddec29253e3..996d0be26fc53 100644
--- a/packages/editor/src/components/post-publish-panel/style.scss
+++ b/packages/editor/src/components/post-publish-panel/style.scss
@@ -122,6 +122,7 @@
.components-panel__body-title .components-button {
align-items: flex-start;
+ text-wrap: balance; // Fallback for Safari.
text-wrap: pretty;
}
}
From e57eed571e8aaa7d65394bdcf861b103dee9843f Mon Sep 17 00:00:00 2001
From: George Mamadashvili
Date: Tue, 4 Jun 2024 15:43:04 +0400
Subject: [PATCH 17/17] Inserter: Return the same items when the state and
parameters don't change (#62263)
* Inserter: Return the same items when the state and parameters don't change
* Use stable default
Co-authored-by: Mamaduka
Co-authored-by: ellatrix
Co-authored-by: tyxla
---
.../inserter/hooks/use-block-types-state.js | 15 ++++++++++-----
packages/block-editor/src/store/selectors.js | 4 +++-
2 files changed, 13 insertions(+), 6 deletions(-)
diff --git a/packages/block-editor/src/components/inserter/hooks/use-block-types-state.js b/packages/block-editor/src/components/inserter/hooks/use-block-types-state.js
index 6b9e694c1cdf8..8db23267eee8f 100644
--- a/packages/block-editor/src/components/inserter/hooks/use-block-types-state.js
+++ b/packages/block-editor/src/components/inserter/hooks/use-block-types-state.js
@@ -8,7 +8,7 @@ import {
parse,
} from '@wordpress/blocks';
import { useSelect } from '@wordpress/data';
-import { useCallback } from '@wordpress/element';
+import { useCallback, useMemo } from '@wordpress/element';
/**
* Internal dependencies
@@ -25,13 +25,18 @@ import { withRootClientIdOptionKey } from '../../../store/utils';
* @return {Array} Returns the block types state. (block types, categories, collections, onSelect handler)
*/
const useBlockTypesState = ( rootClientId, onInsert, isQuick ) => {
+ const options = useMemo(
+ () => ( { [ withRootClientIdOptionKey ]: ! isQuick } ),
+ [ isQuick ]
+ );
const [ items ] = useSelect(
( select ) => [
- select( blockEditorStore ).getInserterItems( rootClientId, {
- [ withRootClientIdOptionKey ]: ! isQuick,
- } ),
+ select( blockEditorStore ).getInserterItems(
+ rootClientId,
+ options
+ ),
],
- [ rootClientId, isQuick ]
+ [ rootClientId, options ]
);
const [ categories, collections ] = useSelect( ( select ) => {
diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js
index bf7b5125a770e..bf98521dfe9b6 100644
--- a/packages/block-editor/src/store/selectors.js
+++ b/packages/block-editor/src/store/selectors.js
@@ -76,6 +76,8 @@ const EMPTY_ARRAY = [];
*/
const EMPTY_SET = new Set();
+const EMPTY_OBJECT = {};
+
/**
* Returns a block's name given its client ID, or null if no block exists with
* the client ID.
@@ -1996,7 +1998,7 @@ const buildBlockTypeItem =
*/
export const getInserterItems = createRegistrySelector( ( select ) =>
createSelector(
- ( state, rootClientId = null, options = {} ) => {
+ ( state, rootClientId = null, options = EMPTY_OBJECT ) => {
const buildReusableBlockInserterItem = ( reusableBlock ) => {
const icon = ! reusableBlock.wp_pattern_sync_status
? {