From e8639285e2a60a86fc5979fffcf202c746029d0d Mon Sep 17 00:00:00 2001 From: George Mamadashvili Date: Tue, 8 Mar 2022 15:59:48 +0000 Subject: [PATCH 01/17] Update 'clickMenuItem' test util to use full label matching (#39274) * Update 'clickMenuItem' test util to use full label matching * Update changelog * Change wording --- packages/e2e-test-utils/CHANGELOG.md | 4 ++++ packages/e2e-test-utils/src/click-menu-item.js | 4 +--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/e2e-test-utils/CHANGELOG.md b/packages/e2e-test-utils/CHANGELOG.md index 970525f85241e6..0cc876370aee4a 100644 --- a/packages/e2e-test-utils/CHANGELOG.md +++ b/packages/e2e-test-utils/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Breaking Changes + +- Updated `clickMenuItem` method to use exact label matching instead of partial [#39274](https://github.com/WordPress/gutenberg/pull/39274). + ### Enhancement - The `toggleMoreMenu` and `clickMoreMenuItem` utilities no longer require a second 'context' parameter. diff --git a/packages/e2e-test-utils/src/click-menu-item.js b/packages/e2e-test-utils/src/click-menu-item.js index e4a29eacf39e60..1bf34fda50c51f 100644 --- a/packages/e2e-test-utils/src/click-menu-item.js +++ b/packages/e2e-test-utils/src/click-menu-item.js @@ -10,9 +10,7 @@ import { first } from 'lodash'; */ export async function clickMenuItem( label ) { const elementToClick = first( - await page.$x( - `//div[@role="menu"]//span[contains(concat(" ", @class, " "), " components-menu-item__item ")][contains(text(), "${ label }")]` - ) + await page.$x( `//*[@role="menu"]//*[text()="${ label }"]` ) ); await elementToClick.click(); } From 45a2e014b0b131254b3b244f7e49dfe4bc28e33e Mon Sep 17 00:00:00 2001 From: Glen Davies Date: Wed, 9 Mar 2022 11:21:21 +1300 Subject: [PATCH 02/17] Add additional selector to account for the move of is-style classes from the deprecated align div in https://github.com/WordPress/gutenberg/commit/e04ec5655baea387fab421b28ff846626ae696c6 (#39295) Co-authored-by: Glen Davies --- packages/block-library/src/image/style.scss | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/block-library/src/image/style.scss b/packages/block-library/src/image/style.scss index 564cdad7270e2e..dbce34857299b2 100644 --- a/packages/block-library/src/image/style.scss +++ b/packages/block-library/src/image/style.scss @@ -69,7 +69,8 @@ } // Variations - &.is-style-rounded img { + &.is-style-rounded img, + .is-style-rounded img { // We use an absolute pixel to prevent the oval shape that a value of 50% would give // to rectangular images. A pill-shape is better than otherwise. border-radius: 9999px; From 817651ee0d0882cf252a1c81b11fe10a9cce6875 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation Date: Tue, 8 Mar 2022 22:38:34 +0000 Subject: [PATCH 03/17] Bump plugin version to 12.7.1 --- gutenberg.php | 2 +- package-lock.json | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gutenberg.php b/gutenberg.php index 9f709b1edee83c..4621513aebbbba 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -5,7 +5,7 @@ * Description: Printing since 1440. This is the development plugin for the new block editor in core. * Requires at least: 5.8 * Requires PHP: 5.6 - * Version: 12.7.0 + * Version: 12.7.1 * Author: Gutenberg Team * Text Domain: gutenberg * diff --git a/package-lock.json b/package-lock.json index 6e57be69135ef4..89d67a685f5bf6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "gutenberg", - "version": "12.7.0", + "version": "12.7.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 9f4b25722c7d80..5994b2b5587d20 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gutenberg", - "version": "12.7.0", + "version": "12.7.1", "private": true, "description": "A new WordPress editor experience.", "author": "The WordPress Contributors", From 5f265e9e4200479f50d7310a40cc6c8a755fedb8 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation Date: Tue, 8 Mar 2022 22:47:28 +0000 Subject: [PATCH 04/17] Update Changelog for 12.7.1 --- changelog.txt | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/changelog.txt b/changelog.txt index 18761d87fb0ef2..ba83bcc61d98d8 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,23 @@ == Changelog == += 12.7.1 = + + + +## Changelog + +### Bug Fixes + +#### Block Library +- Image block: Add additional selector to account for the move of is-style classes. ([39295](https://github.com/WordPress/gutenberg/pull/39295)) + +## Contributors + +The following contributors merged PRs in this release: + +@glendaviesnz + + = 12.7.0 = ## Changelog From c64e6b3457f55d400de812c0d537c9c5b15dea12 Mon Sep 17 00:00:00 2001 From: Jos Date: Wed, 9 Mar 2022 14:01:00 +0800 Subject: [PATCH 05/17] Remove rename rn UI tests (#39042) * remove redundant tests and rename incorrect tests * remove extra space * remove console log * revert test removal * add newline * update test case description Co-authored-by: jos <17252150+jostnes@users.noreply.github.com> --- .../gutenberg-editor-block-insertion.test.js | 3 +-- .../gutenberg-editor-more.test.js | 8 ++++---- .../gutenberg-editor-paragraph.test.js | 16 ---------------- .../gutenberg-editor-separator.test.js | 2 +- .../gutenberg-editor-spacer.test.js | 6 +++--- 5 files changed, 9 insertions(+), 26 deletions(-) diff --git a/packages/react-native-editor/__device-tests__/gutenberg-editor-block-insertion.test.js b/packages/react-native-editor/__device-tests__/gutenberg-editor-block-insertion.test.js index 21482d52310594..0ee6a985c4f921 100644 --- a/packages/react-native-editor/__device-tests__/gutenberg-editor-block-insertion.test.js +++ b/packages/react-native-editor/__device-tests__/gutenberg-editor-block-insertion.test.js @@ -6,7 +6,7 @@ import { isAndroid, swipeDown, clickMiddleOfElement } from './helpers/utils'; import testData from './helpers/test-data'; describe( 'Gutenberg Editor tests for Block insertion', () => { - it( 'should be able to insert block into post', async () => { + it( 'should be able to insert multi-paragraph text, and text to another paragraph block in between', async () => { await editorPage.addNewBlock( blockNames.paragraph ); let paragraphBlockElement = await editorPage.getBlockAtPosition( blockNames.paragraph @@ -117,7 +117,6 @@ describe( 'Gutenberg Editor tests for Block insertion', () => { await editorPage.sendTextToParagraphBlock( 1, testData.mediumText ); await paragraphBlockElement.click(); const html = await editorPage.getHtmlContent(); - expect( html.toLowerCase() ).toBe( testData.blockInsertionHtmlFromTitle.toLowerCase() ); diff --git a/packages/react-native-editor/__device-tests__/gutenberg-editor-more.test.js b/packages/react-native-editor/__device-tests__/gutenberg-editor-more.test.js index 115a849df3df61..a98627aa5c801c 100644 --- a/packages/react-native-editor/__device-tests__/gutenberg-editor-more.test.js +++ b/packages/react-native-editor/__device-tests__/gutenberg-editor-more.test.js @@ -3,14 +3,14 @@ */ import { blockNames } from './pages/editor-page'; -describe( 'Gutenberg Editor Spacer Block test', () => { - it( 'should be able to add an separator block', async () => { +describe( 'Gutenberg Editor More Block test', () => { + it( 'should be able to add a more block', async () => { await editorPage.addNewBlock( blockNames.more ); - const separatorBlock = await editorPage.getBlockAtPosition( + const moreBlock = await editorPage.getBlockAtPosition( blockNames.more ); - expect( separatorBlock ).toBeTruthy(); + expect( moreBlock ).toBeTruthy(); await editorPage.removeBlockAtPosition( blockNames.more ); } ); } ); diff --git a/packages/react-native-editor/__device-tests__/gutenberg-editor-paragraph.test.js b/packages/react-native-editor/__device-tests__/gutenberg-editor-paragraph.test.js index 9bcae9115ecc6c..f9afa06ebe7378 100644 --- a/packages/react-native-editor/__device-tests__/gutenberg-editor-paragraph.test.js +++ b/packages/react-native-editor/__device-tests__/gutenberg-editor-paragraph.test.js @@ -11,22 +11,6 @@ import { import testData from './helpers/test-data'; describe( 'Gutenberg Editor tests for Paragraph Block', () => { - it( 'should be able to add a new Paragraph block', async () => { - await editorPage.addNewBlock( blockNames.paragraph ); - const paragraphBlockElement = await editorPage.getBlockAtPosition( - blockNames.paragraph - ); - if ( isAndroid() ) { - await paragraphBlockElement.click(); - } - - await editorPage.typeTextToParagraphBlock( - paragraphBlockElement, - testData.shortText - ); - await editorPage.removeBlockAtPosition( blockNames.paragraph ); - } ); - it( 'should be able to split one paragraph block into two', async () => { await editorPage.addNewBlock( blockNames.paragraph ); const paragraphBlockElement = await editorPage.getBlockAtPosition( diff --git a/packages/react-native-editor/__device-tests__/gutenberg-editor-separator.test.js b/packages/react-native-editor/__device-tests__/gutenberg-editor-separator.test.js index 34c0551bcbd464..08b2b5b4709d3e 100644 --- a/packages/react-native-editor/__device-tests__/gutenberg-editor-separator.test.js +++ b/packages/react-native-editor/__device-tests__/gutenberg-editor-separator.test.js @@ -4,7 +4,7 @@ import { blockNames } from './pages/editor-page'; describe( 'Gutenberg Editor Separator Block test', () => { - it( 'should be able to add an separator block', async () => { + it( 'should be able to add a separator block', async () => { await editorPage.addNewBlock( blockNames.separator ); const separatorBlock = await editorPage.getBlockAtPosition( blockNames.separator diff --git a/packages/react-native-editor/__device-tests__/gutenberg-editor-spacer.test.js b/packages/react-native-editor/__device-tests__/gutenberg-editor-spacer.test.js index febd3fb8f6d81e..721ae86ea7eee4 100644 --- a/packages/react-native-editor/__device-tests__/gutenberg-editor-spacer.test.js +++ b/packages/react-native-editor/__device-tests__/gutenberg-editor-spacer.test.js @@ -4,13 +4,13 @@ import { blockNames } from './pages/editor-page'; describe( 'Gutenberg Editor Spacer Block test', () => { - it( 'should be able to add an separator block', async () => { + it( 'should be able to add a spacer block', async () => { await editorPage.addNewBlock( blockNames.spacer ); - const separatorBlock = await editorPage.getBlockAtPosition( + const spacerBlock = await editorPage.getBlockAtPosition( blockNames.spacer ); - expect( separatorBlock ).toBeTruthy(); + expect( spacerBlock ).toBeTruthy(); await editorPage.removeBlockAtPosition( blockNames.spacer ); } ); } ); From 9ffe47046e68c11e97b198f4d650c6b38d6f524e Mon Sep 17 00:00:00 2001 From: Joshua Fredrickson Date: Wed, 9 Mar 2022 00:05:29 -0600 Subject: [PATCH 06/17] Add a resolvable JavaScript entry point to base-styles (#39240) * Add index.js * Play nice with prettier * Make the comment more descriptive --- packages/base-styles/index.js | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 packages/base-styles/index.js diff --git a/packages/base-styles/index.js b/packages/base-styles/index.js new file mode 100644 index 00000000000000..cc5b9f492020cf --- /dev/null +++ b/packages/base-styles/index.js @@ -0,0 +1,4 @@ +/** + * This file is intentionally left blank and acts as + * a resolvable JavaScript entry point for this package. + */ From a0e45594ab0f73839f939259e546561f718daccd Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Wed, 9 Mar 2022 06:52:51 +0000 Subject: [PATCH 07/17] Improve create new UI feedback in Nav block (#39219) * Refactor hook to async pattern with state * Extract createNavigation to top level edit and provide UI feedback * Extract createNavigation to top level edit and provide UI feedback * Handle create empty in upper component * Expose errors to improve debugging * Implement notices for menu creation * Ensure fallback title by waiting on default title generation * Guard against empty Navigation title * Remove unused hook introduced via rebase * Export and use status constants for create menu hook * Rename function name to better communicate intent * Fix convert classic menu hook to conform to new create hook API * Use status constants * Fix test by ensuring reference to Nav block is current when unfocused. * Add test for loading indicator whilst creating Navigation * Add test for notice upon creation of empty Navigation Menu --- .../src/navigation/edit/index.js | 73 ++++++++++++++++--- .../src/navigation/edit/placeholder/index.js | 21 +----- .../navigation/edit/unsaved-inner-blocks.js | 4 +- .../use-convert-classic-menu-to-block-menu.js | 4 +- .../edit/use-create-navigation-menu.js | 67 +++++++++++++++-- .../specs/editor/blocks/navigation.test.js | 70 ++++++++++++++++-- 6 files changed, 194 insertions(+), 45 deletions(-) diff --git a/packages/block-library/src/navigation/edit/index.js b/packages/block-library/src/navigation/edit/index.js index 7b15d775f281a3..0c60ff4993aa56 100644 --- a/packages/block-library/src/navigation/edit/index.js +++ b/packages/block-library/src/navigation/edit/index.js @@ -61,6 +61,11 @@ import useConvertClassicToBlockMenu, { CLASSIC_MENU_CONVERSION_PENDING, CLASSIC_MENU_CONVERSION_SUCCESS, } from './use-convert-classic-menu-to-block-menu'; +import useCreateNavigationMenu, { + CREATE_NAVIGATION_MENU_ERROR, + CREATE_NAVIGATION_MENU_PENDING, + CREATE_NAVIGATION_MENU_SUCCESS, +} from './use-create-navigation-menu'; const EMPTY_ARRAY = []; @@ -162,6 +167,51 @@ function Navigation( { // the Select Menu dropdown. useNavigationEntities(); + const [ + showNavigationMenuCreateNotice, + hideNavigationMenuCreateNotice, + ] = useNavigationNotice( { + name: 'block-library/core/navigation/create', + } ); + + const { + create: createNavigationMenu, + status: createNavigationMenuStatus, + error: createNavigationMenuError, + value: createNavigationMenuPost, + } = useCreateNavigationMenu( clientId ); + + const isCreatingNavigationMenu = + createNavigationMenuStatus === CREATE_NAVIGATION_MENU_PENDING; + + useEffect( () => { + hideNavigationMenuCreateNotice(); + + if ( createNavigationMenuStatus === CREATE_NAVIGATION_MENU_PENDING ) { + speak( __( `Creating Navigation Menu.` ) ); + } + + if ( createNavigationMenuStatus === CREATE_NAVIGATION_MENU_SUCCESS ) { + setRef( createNavigationMenuPost.id ); + selectBlock( clientId ); + + showNavigationMenuCreateNotice( + __( `Navigation Menu successfully created.` ) + ); + } + + if ( createNavigationMenuStatus === CREATE_NAVIGATION_MENU_ERROR ) { + showNavigationMenuCreateNotice( + __( 'Failed to create Navigation Menu.' ) + ); + } + }, [ + createNavigationMenu, + createNavigationMenuStatus, + createNavigationMenuError, + createNavigationMenuPost, + ] ); + const { hasUncontrolledInnerBlocks, uncontrolledInnerBlocks, @@ -251,12 +301,14 @@ function Navigation( { const TagName = 'nav'; // "placeholder" shown if: - // - we don't have a ref attribute pointing to a Navigation Post. - // - we are not running a menu conversion process. - // - we don't have uncontrolled blocks. - // - (legacy) we have a Navigation Area without a ref attribute pointing to a Navigation Post. + // - there is no ref attribute pointing to a Navigation Post. + // - there is no classic menu conversion process in progress. + // - there is no menu creation process in progress. + // - there are no uncontrolled blocks. + // - (legacy) there is a Navigation Area without a ref attribute pointing to a Navigation Post. const isPlaceholder = ! ref && + ! isCreatingNavigationMenu && ! isConvertingClassicMenu && ( ! hasUncontrolledInnerBlocks || isWithinUnassignedArea ); @@ -264,11 +316,13 @@ function Navigation( { ! isNavigationMenuMissing && isNavigationMenuResolved; // "loading" state: - // - we are running the Classic Menu conversion process. + // - there is a menu creation process in progress. + // - there is a classic menu conversion process in progress. // OR // - there is a ref attribute pointing to a Navigation Post // - the Navigation Post isn't available (hasn't resolved) yet. const isLoading = + isCreatingNavigationMenu || isConvertingClassicMenu || !! ( ref && ! isEntityAvailable && ! isConvertingClassicMenu ); @@ -466,7 +520,7 @@ function Navigation( { [ convert, handleUpdateMenu ] ); - const startWithEmptyMenu = useCallback( () => { + const resetToEmptyBlock = useCallback( () => { registry.batch( () => { if ( navigationArea ) { setAreaMenu( 0 ); @@ -528,7 +582,7 @@ function Navigation( { { __( 'Navigation menu has been deleted or is unavailable. ' ) } - @@ -569,6 +623,7 @@ function Navigation( { isResolvingCanUserCreateNavigationMenu } onFinish={ handleSelectNavigation } + onCreateEmpty={ () => createNavigationMenu( '', [] ) } /> ); @@ -584,7 +639,7 @@ function Navigation( { currentMenuId={ ref } clientId={ clientId } onSelect={ handleSelectNavigation } - onCreateNew={ startWithEmptyMenu } + onCreateNew={ resetToEmptyBlock } /* translators: %s: The name of a menu. */ actionLabel={ __( "Switch to '%s'" ) } showManageActions @@ -739,7 +794,7 @@ function Navigation( { { hasResolvedCanUserDeleteNavigationMenu && canUserDeleteNavigationMenu && ( ) } diff --git a/packages/block-library/src/navigation/edit/placeholder/index.js b/packages/block-library/src/navigation/edit/placeholder/index.js index 9906e37244eed4..e1b50e253a292f 100644 --- a/packages/block-library/src/navigation/edit/placeholder/index.js +++ b/packages/block-library/src/navigation/edit/placeholder/index.js @@ -12,7 +12,6 @@ import { useEffect } from '@wordpress/element'; */ import useNavigationEntities from '../../use-navigation-entities'; import PlaceholderPreview from './placeholder-preview'; -import useCreateNavigationMenu from '../use-create-navigation-menu'; import NavigationMenuSelector from '../navigation-menu-selector'; export default function NavigationPlaceholder( { @@ -22,26 +21,10 @@ export default function NavigationPlaceholder( { canUserCreateNavigationMenu = false, isResolvingCanUserCreateNavigationMenu, onFinish, + onCreateEmpty, } ) { - const createNavigationMenu = useCreateNavigationMenu( clientId ); - - const onFinishMenuCreation = async ( - blocks, - navigationMenuTitle = null - ) => { - const navigationMenu = await createNavigationMenu( - navigationMenuTitle, - blocks - ); - onFinish( navigationMenu, blocks ); - }; - const { isResolvingMenus, hasResolvedMenus } = useNavigationEntities(); - const onCreateEmptyMenu = () => { - onFinishMenuCreation( [] ); - }; - useEffect( () => { if ( ! isSelected ) { return; @@ -98,7 +81,7 @@ export default function NavigationPlaceholder( { { canUserCreateNavigationMenu && ( diff --git a/packages/block-library/src/navigation/edit/unsaved-inner-blocks.js b/packages/block-library/src/navigation/edit/unsaved-inner-blocks.js index 030a7dbbfdd37e..bf8edc12eac1fb 100644 --- a/packages/block-library/src/navigation/edit/unsaved-inner-blocks.js +++ b/packages/block-library/src/navigation/edit/unsaved-inner-blocks.js @@ -72,7 +72,9 @@ export default function UnsavedInnerBlocks( { const { hasResolvedNavigationMenus, navigationMenus } = useNavigationMenu(); - const createNavigationMenu = useCreateNavigationMenu( clientId ); + const { create: createNavigationMenu } = useCreateNavigationMenu( + clientId + ); // Automatically save the uncontrolled blocks. useEffect( async () => { diff --git a/packages/block-library/src/navigation/edit/use-convert-classic-menu-to-block-menu.js b/packages/block-library/src/navigation/edit/use-convert-classic-menu-to-block-menu.js index 475d232b4735f6..569c142ae9bb4c 100644 --- a/packages/block-library/src/navigation/edit/use-convert-classic-menu-to-block-menu.js +++ b/packages/block-library/src/navigation/edit/use-convert-classic-menu-to-block-menu.js @@ -18,7 +18,9 @@ export const CLASSIC_MENU_CONVERSION_PENDING = 'pending'; export const CLASSIC_MENU_CONVERSION_IDLE = 'idle'; function useConvertClassicToBlockMenu( clientId ) { - const createNavigationMenu = useCreateNavigationMenu( clientId ); + const { create: createNavigationMenu } = useCreateNavigationMenu( + clientId + ); const registry = useRegistry(); const [ status, setStatus ] = useState( CLASSIC_MENU_CONVERSION_IDLE ); diff --git a/packages/block-library/src/navigation/edit/use-create-navigation-menu.js b/packages/block-library/src/navigation/edit/use-create-navigation-menu.js index 39d54953587f06..14135c84c8d94c 100644 --- a/packages/block-library/src/navigation/edit/use-create-navigation-menu.js +++ b/packages/block-library/src/navigation/edit/use-create-navigation-menu.js @@ -4,23 +4,58 @@ import { serialize } from '@wordpress/blocks'; import { store as coreStore } from '@wordpress/core-data'; import { useDispatch } from '@wordpress/data'; -import { useCallback } from '@wordpress/element'; +import { useState, useCallback } from '@wordpress/element'; /** * Internal dependencies */ import useGenerateDefaultNavigationTitle from './use-generate-default-navigation-title'; +export const CREATE_NAVIGATION_MENU_SUCCESS = 'success'; +export const CREATE_NAVIGATION_MENU_ERROR = 'error'; +export const CREATE_NAVIGATION_MENU_PENDING = 'pending'; +export const CREATE_NAVIGATION_MENU_IDLE = 'idle'; + export default function useCreateNavigationMenu( clientId ) { + const [ status, setStatus ] = useState( CREATE_NAVIGATION_MENU_IDLE ); + const [ value, setValue ] = useState( null ); + const [ error, setError ] = useState( null ); + const { saveEntityRecord } = useDispatch( coreStore ); const generateDefaultTitle = useGenerateDefaultNavigationTitle( clientId ); // This callback uses data from the two placeholder steps and only creates // a new navigation menu when the user completes the final step. - return useCallback( + const create = useCallback( async ( title = null, blocks = [] ) => { + // Guard against creating Navigations without a title. + // Note you can pass no title, but if one is passed it must be + // a string otherwise the title may end up being empty. + if ( title && typeof title !== 'string' ) { + setError( + 'Invalid title supplied when creating Navigation Menu.' + ); + setStatus( CREATE_NAVIGATION_MENU_ERROR ); + throw new Error( + `Value of supplied title argument was not a string.` + ); + } + + setStatus( CREATE_NAVIGATION_MENU_PENDING ); + setValue( null ); + setError( null ); + if ( ! title ) { - title = await generateDefaultTitle(); + title = await generateDefaultTitle().catch( ( err ) => { + setError( err?.message ); + setStatus( CREATE_NAVIGATION_MENU_ERROR ); + throw new Error( + 'Failed to create title when saving new Navigation Menu.', + { + cause: err, + } + ); + } ); } const record = { title, @@ -28,12 +63,28 @@ export default function useCreateNavigationMenu( clientId ) { status: 'publish', }; - return await saveEntityRecord( - 'postType', - 'wp_navigation', - record - ); + // Return affords ability to await on this function directly + return saveEntityRecord( 'postType', 'wp_navigation', record ) + .then( ( response ) => { + setValue( response ); + setStatus( CREATE_NAVIGATION_MENU_SUCCESS ); + return response; + } ) + .catch( ( err ) => { + setError( err?.message ); + setStatus( CREATE_NAVIGATION_MENU_ERROR ); + throw new Error( 'Unable to save new Navigation Menu', { + cause: err, + } ); + } ); }, [ serialize, saveEntityRecord ] ); + + return { + create, + status, + value, + error, + }; } diff --git a/packages/e2e-tests/specs/editor/blocks/navigation.test.js b/packages/e2e-tests/specs/editor/blocks/navigation.test.js index e3d8f8739a7378..5a6fdfd7c34c6c 100644 --- a/packages/e2e-tests/specs/editor/blocks/navigation.test.js +++ b/packages/e2e-tests/specs/editor/blocks/navigation.test.js @@ -340,6 +340,53 @@ describe( 'Navigation', () => { // Resolve the controlled mocked API request. resolveNavigationRequest(); } ); + + it( 'shows a loading indicator whilst empty Navigation menu is being created', async () => { + const testNavId = 1; + + let resolveNavigationRequest; + + // Mock the request for the single Navigation post in order to fully + // control the resolution of the request. This will enable the ability + // to assert on how the UI responds during the API resolution without + // relying on variable factors such as network conditions. + await setUpResponseMocking( [ + { + match: ( request ) => + request.url().includes( `rest_route` ) && + request.url().includes( `navigation` ) && + request.url().includes( testNavId ), + onRequestMatch: () => { + // The Promise simulates a REST API request whose resolultion + // the test has full control over. + return new Promise( ( resolve ) => { + // Assign the resolution function to the var in the + // upper scope to afford control over resolution. + resolveNavigationRequest = resolve; + } ); + }, + }, + ] ); + + await createNewPost(); + await insertBlock( 'Navigation' ); + + let navBlock = await waitForBlock( 'Navigation' ); + + // Create empty Navigation block with no items + const startEmptyButton = await page.waitForXPath( + START_EMPTY_XPATH + ); + await startEmptyButton.click(); + + navBlock = await waitForBlock( 'Navigation' ); + + // Check for the spinner to be present whilst loading. + await navBlock.waitForSelector( '.components-spinner' ); + + // Resolve the controlled mocked API request. + resolveNavigationRequest(); + } ); } ); describe( 'Placeholder', () => { @@ -357,9 +404,9 @@ describe( 'Navigation', () => { // Check for unconfigured Placeholder state to display await page.waitForXPath( START_EMPTY_XPATH ); - // Deselect the Nav block. - await page.keyboard.press( 'Escape' ); - await page.keyboard.press( 'Escape' ); + // Deselect the Nav block by inserting a new block at the root level + // outside of the Nav block. + await insertBlock( 'Paragraph' ); const navBlock = await waitForBlock( 'Navigation' ); @@ -386,11 +433,15 @@ describe( 'Navigation', () => { ); await startEmptyButton.click(); - const navBlock = await waitForBlock( 'Navigation' ); + // Wait for block to resolve + let navBlock = await waitForBlock( 'Navigation' ); + + // Deselect the Nav block by inserting a new block at the root level + // outside of the Nav block. + await insertBlock( 'Paragraph' ); - // Deselect the Nav block. - await page.keyboard.press( 'Escape' ); - await page.keyboard.press( 'Escape' ); + // Aquire fresh reference to block + navBlock = await waitForBlock( 'Navigation' ); // Check Placeholder Preview is visible. await navBlock.waitForSelector( @@ -462,6 +513,11 @@ describe( 'Navigation', () => { const startEmptyButton = await page.waitForXPath( START_EMPTY_XPATH ); await startEmptyButton.click(); + // Await "success" notice. + await page.waitForXPath( + '//div[@class="components-snackbar__content"][contains(text(), "Navigation Menu successfully created.")]' + ); + const appender = await page.waitForSelector( '.wp-block-navigation .block-list-appender' ); From d10329149ce45ef3dd9572fb0a03ebff548cc092 Mon Sep 17 00:00:00 2001 From: tellthemachines Date: Wed, 9 Mar 2022 19:01:43 +1100 Subject: [PATCH 08/17] Add interface preferences modal to edit post. (#39176) * Add interface preferences modal to edit post. * Update unit tests * Update to modal tabs component. * Update to use unstable component. * Update tests. * Remove unused components. * Update meta boxes to use new Section component. * Remove unused CSS. * Remove stylesheet import. --- .../specs/editor/various/preview.test.js | 4 +- .../edit-post/src/components/layout/index.js | 4 +- .../src/components/preferences-modal/index.js | 174 +---- .../preferences-modal/meta-boxes-section.js | 6 +- .../preferences-modal/options/base.js | 20 - .../options/enable-custom-fields.js | 6 +- .../options/enable-feature.js | 2 +- .../preferences-modal/options/enable-panel.js | 2 +- .../options/enable-publish-sidebar.js | 6 +- .../enable-custom-fields.js.snap | 8 +- .../options/test/enable-custom-fields.js | 2 +- .../components/preferences-modal/section.js | 15 - .../components/preferences-modal/style.scss | 112 ---- .../test/__snapshots__/index.js.snap | 592 +++++++----------- .../preferences-modal/test/index.js | 10 +- packages/edit-post/src/style.scss | 1 - 16 files changed, 280 insertions(+), 684 deletions(-) delete mode 100644 packages/edit-post/src/components/preferences-modal/options/base.js delete mode 100644 packages/edit-post/src/components/preferences-modal/section.js delete mode 100644 packages/edit-post/src/components/preferences-modal/style.scss diff --git a/packages/e2e-tests/specs/editor/various/preview.test.js b/packages/e2e-tests/specs/editor/various/preview.test.js index 2299539fb58b1d..dd3c9e84f8b754 100644 --- a/packages/e2e-tests/specs/editor/various/preview.test.js +++ b/packages/e2e-tests/specs/editor/various/preview.test.js @@ -54,7 +54,7 @@ async function waitForPreviewNavigation( previewPage ) { * @param {boolean} shouldBeChecked If true, turns the option on. If false, off. */ async function toggleCustomFieldsOption( shouldBeChecked ) { - const baseXPath = '//*[contains(@class, "edit-post-preferences-modal")]'; + const baseXPath = '//*[contains(@class, "interface-preferences-modal")]'; const paneslXPath = `${ baseXPath }//button[contains(text(), "Panels")]`; const checkboxXPath = `${ baseXPath }//label[contains(text(), "Custom fields")]`; await clickOnMoreMenuItem( 'Preferences' ); @@ -83,7 +83,7 @@ async function toggleCustomFieldsOption( shouldBeChecked ) { return; } - await clickOnCloseModalButton( '.edit-post-preferences-modal' ); + await clickOnCloseModalButton( '.interface-preferences-modal' ); } describe( 'Preview', () => { diff --git a/packages/edit-post/src/components/layout/index.js b/packages/edit-post/src/components/layout/index.js index 989c185943c2c6..50e388f31b3c85 100644 --- a/packages/edit-post/src/components/layout/index.js +++ b/packages/edit-post/src/components/layout/index.js @@ -38,7 +38,7 @@ import TextEditor from '../text-editor'; import VisualEditor from '../visual-editor'; import EditPostKeyboardShortcuts from '../keyboard-shortcuts'; import KeyboardShortcutHelpModal from '../keyboard-shortcut-help-modal'; -import PreferencesModal from '../preferences-modal'; +import EditPostPreferencesModal from '../preferences-modal'; import BrowserURL from '../browser-url'; import Header from '../header'; import InserterSidebar from '../secondary-sidebar/inserter-sidebar'; @@ -283,7 +283,7 @@ function Layout( { styles } ) { next: nextShortcut, } } /> - + diff --git a/packages/edit-post/src/components/preferences-modal/index.js b/packages/edit-post/src/components/preferences-modal/index.js index e718c048ab08c2..392099aae3300f 100644 --- a/packages/edit-post/src/components/preferences-modal/index.js +++ b/packages/edit-post/src/components/preferences-modal/index.js @@ -6,27 +6,11 @@ import { get } from 'lodash'; /** * WordPress dependencies */ -import { - __experimentalNavigatorProvider as NavigatorProvider, - __experimentalNavigatorScreen as NavigatorScreen, - __experimentalNavigatorButton as NavigatorButton, - __experimentalNavigatorBackButton as NavigatorBackButton, - __experimentalItemGroup as ItemGroup, - __experimentalItem as Item, - __experimentalHStack as HStack, - __experimentalText as Text, - __experimentalTruncate as Truncate, - FlexItem, - Modal, - TabPanel, - Card, - CardHeader, - CardBody, -} from '@wordpress/components'; -import { isRTL, __ } from '@wordpress/i18n'; + +import { __ } from '@wordpress/i18n'; import { useViewportMatch } from '@wordpress/compose'; import { useSelect, useDispatch } from '@wordpress/data'; -import { useMemo, useCallback, useState } from '@wordpress/element'; +import { useMemo } from '@wordpress/element'; import { PostTaxonomies, PostExcerptCheck, @@ -36,12 +20,16 @@ import { store as editorStore, } from '@wordpress/editor'; import { store as coreStore } from '@wordpress/core-data'; -import { chevronLeft, chevronRight, Icon } from '@wordpress/icons'; +import { + PreferencesModal, + PreferencesModalTabs, + PreferencesModalSection, +} from '@wordpress/interface'; /** * Internal dependencies */ -import Section from './section'; + import { EnablePluginDocumentSettingPanelOption, EnablePublishSidebarOption, @@ -53,9 +41,8 @@ import { store as editPostStore } from '../../store'; import BlockManager from '../block-manager'; const MODAL_NAME = 'edit-post/preferences'; -const PREFERENCES_MENU = 'preferences-menu'; -export default function PreferencesModal() { +export default function EditPostPreferencesModal() { const isLargeViewport = useViewportMatch( 'medium' ); const { closeModal } = useDispatch( editPostStore ); const { isModalActive, isViewable } = useSelect( ( select ) => { @@ -91,7 +78,7 @@ export default function PreferencesModal() { content: ( <> { isLargeViewport && ( -
-
+ ) } -
) } -
+ ), }, @@ -158,7 +145,7 @@ export default function PreferencesModal() { tabLabel: __( 'Blocks' ), content: ( <> -
-
-
+ -
+ ), }, @@ -197,7 +184,7 @@ export default function PreferencesModal() { tabLabel: __( 'Panels' ), content: ( <> -
-
+ - sections.reduce( - ( accumulator, { name, tabLabel: title, content } ) => { - accumulator.tabs.push( { name, title } ); - accumulator.sectionsContentMap[ name ] = content; - return accumulator; - }, - { tabs: [], sectionsContentMap: {} } - ), - [ sections ] - ); - const getCurrentTab = useCallback( - ( tab ) => sectionsContentMap[ tab.name ] || null, - [ sectionsContentMap ] - ); if ( ! isModalActive ) { return null; } - let modalContent; - // We render different components based on the viewport size. - if ( isLargeViewport ) { - modalContent = ( - - { getCurrentTab } - - ); - } else { - modalContent = ( - - - - - - { tabs.map( ( tab ) => { - return ( - - - - - { tab.title } - - - - - - - - ); - } ) } - - - - - { sections.map( ( section ) => { - return ( - - - - - { section.tabLabel } - - { section.content } - - - ); - } ) } - - ); - } + return ( - - { modalContent } - + + + ); } diff --git a/packages/edit-post/src/components/preferences-modal/meta-boxes-section.js b/packages/edit-post/src/components/preferences-modal/meta-boxes-section.js index eded51abbbfb59..857eb27910bed6 100644 --- a/packages/edit-post/src/components/preferences-modal/meta-boxes-section.js +++ b/packages/edit-post/src/components/preferences-modal/meta-boxes-section.js @@ -9,11 +9,11 @@ import { filter, map } from 'lodash'; import { __ } from '@wordpress/i18n'; import { withSelect } from '@wordpress/data'; import { store as editorStore } from '@wordpress/editor'; +import { PreferencesModalSection } from '@wordpress/interface'; /** * Internal dependencies */ -import Section from './section'; import { EnableCustomFieldsOption, EnablePanelOption } from './options'; import { store as editPostStore } from '../../store'; @@ -33,7 +33,7 @@ export function MetaBoxesSection( { } return ( -
+ { areCustomFieldsRegistered && ( ) } @@ -44,7 +44,7 @@ export function MetaBoxesSection( { panelName={ `meta-box-${ id }` } /> ) ) } -
+ ); } diff --git a/packages/edit-post/src/components/preferences-modal/options/base.js b/packages/edit-post/src/components/preferences-modal/options/base.js deleted file mode 100644 index b1edfc18a6de18..00000000000000 --- a/packages/edit-post/src/components/preferences-modal/options/base.js +++ /dev/null @@ -1,20 +0,0 @@ -/** - * WordPress dependencies - */ -import { ToggleControl } from '@wordpress/components'; - -function BaseOption( { help, label, isChecked, onChange, children } ) { - return ( -
- - { children } -
- ); -} - -export default BaseOption; diff --git a/packages/edit-post/src/components/preferences-modal/options/enable-custom-fields.js b/packages/edit-post/src/components/preferences-modal/options/enable-custom-fields.js index 6ab452f228a882..3c826d10824a32 100644 --- a/packages/edit-post/src/components/preferences-modal/options/enable-custom-fields.js +++ b/packages/edit-post/src/components/preferences-modal/options/enable-custom-fields.js @@ -6,11 +6,7 @@ import { __ } from '@wordpress/i18n'; import { Button } from '@wordpress/components'; import { withSelect } from '@wordpress/data'; import { store as editorStore } from '@wordpress/editor'; - -/** - * Internal dependencies - */ -import BaseOption from './base'; +import { ___unstablePreferencesModalBaseOption as BaseOption } from '@wordpress/interface'; export function CustomFieldsConfirmation( { willEnable } ) { const [ isReloading, setIsReloading ] = useState( false ); diff --git a/packages/edit-post/src/components/preferences-modal/options/enable-feature.js b/packages/edit-post/src/components/preferences-modal/options/enable-feature.js index 315dd2ed656e50..35e126d10d1a84 100644 --- a/packages/edit-post/src/components/preferences-modal/options/enable-feature.js +++ b/packages/edit-post/src/components/preferences-modal/options/enable-feature.js @@ -3,11 +3,11 @@ */ import { compose } from '@wordpress/compose'; import { withSelect, withDispatch } from '@wordpress/data'; +import { ___unstablePreferencesModalBaseOption as BaseOption } from '@wordpress/interface'; /** * Internal dependencies */ -import BaseOption from './base'; import { store as editPostStore } from '../../../store'; export default compose( diff --git a/packages/edit-post/src/components/preferences-modal/options/enable-panel.js b/packages/edit-post/src/components/preferences-modal/options/enable-panel.js index 0a25b4ad4d86a7..aaf95061f71de4 100644 --- a/packages/edit-post/src/components/preferences-modal/options/enable-panel.js +++ b/packages/edit-post/src/components/preferences-modal/options/enable-panel.js @@ -3,11 +3,11 @@ */ import { compose, ifCondition } from '@wordpress/compose'; import { withSelect, withDispatch } from '@wordpress/data'; +import { ___unstablePreferencesModalBaseOption as BaseOption } from '@wordpress/interface'; /** * Internal dependencies */ -import BaseOption from './base'; import { store as editPostStore } from '../../../store'; export default compose( diff --git a/packages/edit-post/src/components/preferences-modal/options/enable-publish-sidebar.js b/packages/edit-post/src/components/preferences-modal/options/enable-publish-sidebar.js index 23287e3705817d..b3ff938765dc29 100644 --- a/packages/edit-post/src/components/preferences-modal/options/enable-publish-sidebar.js +++ b/packages/edit-post/src/components/preferences-modal/options/enable-publish-sidebar.js @@ -5,11 +5,7 @@ import { compose } from '@wordpress/compose'; import { withSelect, withDispatch } from '@wordpress/data'; import { ifViewportMatches } from '@wordpress/viewport'; import { store as editorStore } from '@wordpress/editor'; - -/** - * Internal dependencies - */ -import BaseOption from './base'; +import { ___unstablePreferencesModalBaseOption as BaseOption } from '@wordpress/interface'; export default compose( withSelect( ( select ) => ( { diff --git a/packages/edit-post/src/components/preferences-modal/options/test/__snapshots__/enable-custom-fields.js.snap b/packages/edit-post/src/components/preferences-modal/options/test/__snapshots__/enable-custom-fields.js.snap index a6e01408f2af75..977bc195fea0a8 100644 --- a/packages/edit-post/src/components/preferences-modal/options/test/__snapshots__/enable-custom-fields.js.snap +++ b/packages/edit-post/src/components/preferences-modal/options/test/__snapshots__/enable-custom-fields.js.snap @@ -15,7 +15,7 @@ exports[`EnableCustomFieldsOption renders a checked checkbox and a confirmation }
{ it( 'renders a checked checkbox when custom fields are enabled', () => { diff --git a/packages/edit-post/src/components/preferences-modal/section.js b/packages/edit-post/src/components/preferences-modal/section.js deleted file mode 100644 index 6e8ad792878c85..00000000000000 --- a/packages/edit-post/src/components/preferences-modal/section.js +++ /dev/null @@ -1,15 +0,0 @@ -const Section = ( { description, title, children } ) => ( -
-

- { title } -

- { description && ( -

- { description } -

- ) } - { children } -
-); - -export default Section; diff --git a/packages/edit-post/src/components/preferences-modal/style.scss b/packages/edit-post/src/components/preferences-modal/style.scss deleted file mode 100644 index f72eea64aca6cf..00000000000000 --- a/packages/edit-post/src/components/preferences-modal/style.scss +++ /dev/null @@ -1,112 +0,0 @@ -$vertical-tabs-width: 160px; - -.edit-post-preferences-modal { - // To keep modal dimensions consistent as subsections are navigated, width - // and height are used instead of max-(width/height). - @include break-small() { - width: calc(100% - #{ $grid-unit-20 * 2 }); - height: calc(100% - #{ $header-height * 2 }); - } - @include break-medium() { - width: $break-medium - $grid-unit-20 * 2; - } - @include break-large() { - height: 70%; - } - - // Clears spacing to flush fit the navigator component to the modal edges. - @media (max-width: #{ ($break-medium - 1) }) { - .components-modal__content { - padding: 0; - - &::before { - content: none; - } - } - // Keep the navigator component from overflowing the modal content area - // to ensure that sticky position elements stick where intended. - .components-navigator-provider { - height: 100%; - } - } - - .edit-post-preferences__tabs { - .components-tab-panel__tabs { - position: absolute; - top: $header-height + $grid-unit-30; - // Aligns button text instead of button box. - left: $grid-unit-20; - width: $vertical-tabs-width; - .components-tab-panel__tabs-item { - border-radius: $radius-block-ui; - font-weight: 400; - &.is-active { - background: $gray-100; - box-shadow: none; - font-weight: 500; - } - &:focus:not(:disabled) { - box-shadow: inset 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color); - } - } - } - .components-tab-panel__tab-content { - padding-left: $grid-unit-30; - margin-left: $vertical-tabs-width; - } - } - - &__section { - margin: 0 0 2.5rem 0; - - &:last-child { - margin: 0; - } - } - - &__section-title { - font-size: 0.9rem; - font-weight: 600; - margin-top: 0; - } - - &__option { - .components-base-control { - .components-base-control__field { - align-items: center; - display: flex; - margin-bottom: 0; - - & > label { - flex-grow: 1; - padding: 0.6rem 0 0.6rem 10px; - } - } - } - } - - &__custom-fields-confirmation-message, - &__custom-fields-confirmation-button { - margin: 0 0 0.6rem 48px; - - @include break-medium() { - margin-left: 38px; - } - @include break-small() { - max-width: 300px; - } - } - - .components-base-control__help { - margin: -$grid-unit-10 0 $grid-unit-10 58px; - font-size: $helptext-font-size; - font-style: normal; - color: $gray-700; - } - .edit-post-preferences-modal__section-description { - margin: -$grid-unit-10 0 $grid-unit-10 0; - font-size: $helptext-font-size; - font-style: normal; - color: $gray-700; - } -} diff --git a/packages/edit-post/src/components/preferences-modal/test/__snapshots__/index.js.snap b/packages/edit-post/src/components/preferences-modal/test/__snapshots__/index.js.snap index 4d81822603f10c..8648e9c4ced319 100644 --- a/packages/edit-post/src/components/preferences-modal/test/__snapshots__/index.js.snap +++ b/packages/edit-post/src/components/preferences-modal/test/__snapshots__/index.js.snap @@ -1,384 +1,262 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`PreferencesModal should match snapshot when the modal is active large viewports 1`] = ` - - +
+ +
+
+ + + + + +
+ , "name": "general", - "title": "General", + "tabLabel": "General", }, Object { + "content": +
+ + +
+
+ +
+
, "name": "blocks", - "title": "Blocks", + "tabLabel": "Blocks", }, Object { + "content": +
+ + + + + + + + + + + + + + +
+ +
, "name": "panels", - "title": "Panels", + "tabLabel": "Panels", }, ] } - > - -
-
+ /> + `; -exports[`PreferencesModal should match snapshot when the modal is active small viewports 1`] = ` - - - - - - - +
- - - - General - - - - - - - } - /> - - - - + + + + +
+ , + "name": "general", + "tabLabel": "General", + }, + Object { + "content": +
- - - - Blocks - - - - - - - } - /> - - - - + +
+
- - - - Panels - - - - - - - } - /> - - - - - - - - - - - - +
+
, + "name": "blocks", + "tabLabel": "Blocks", + }, + Object { + "content": +
+ + + + - - } - /> - - General - - - -
- - - - - -
-
- - - - - - - + + - - } - /> - - Blocks - - - -
- - -
-
- -
-
-
-
- - - - + - - - } - /> - - Panels - - - -
- - + + + +
+ - - - - - - - - - - - - -
- -
-
-
-
-
+ , + "name": "panels", + "tabLabel": "Panels", + }, + ] + } + /> + `; diff --git a/packages/edit-post/src/components/preferences-modal/test/index.js b/packages/edit-post/src/components/preferences-modal/test/index.js index 8a461516467a00..376bdecc472f12 100644 --- a/packages/edit-post/src/components/preferences-modal/test/index.js +++ b/packages/edit-post/src/components/preferences-modal/test/index.js @@ -12,31 +12,31 @@ import { useViewportMatch } from '@wordpress/compose'; /** * Internal dependencies */ -import PreferencesModal from '../'; +import EditPostPreferencesModal from '../'; // This allows us to tweak the returned value on each test. jest.mock( '@wordpress/data/src/components/use-select', () => jest.fn() ); jest.mock( '@wordpress/compose/src/hooks/use-viewport-match', () => jest.fn() ); -describe( 'PreferencesModal', () => { +describe( 'EditPostPreferencesModal', () => { describe( 'should match snapshot when the modal is active', () => { it( 'large viewports', () => { useSelect.mockImplementation( () => ( { isModalActive: true } ) ); useViewportMatch.mockImplementation( () => true ); - const wrapper = shallow( ); + const wrapper = shallow( ); expect( wrapper ).toMatchSnapshot(); } ); it( 'small viewports', () => { useSelect.mockImplementation( () => ( { isModalActive: true } ) ); useViewportMatch.mockImplementation( () => false ); - const wrapper = shallow( ); + const wrapper = shallow( ); expect( wrapper ).toMatchSnapshot(); } ); } ); it( 'should not render when the modal is not active', () => { useSelect.mockImplementation( () => ( { isModalActive: false } ) ); - const wrapper = shallow( ); + const wrapper = shallow( ); expect( wrapper.isEmptyRender() ).toBe( true ); } ); } ); diff --git a/packages/edit-post/src/style.scss b/packages/edit-post/src/style.scss index 8db03ae060ab78..a464111f28c1c1 100644 --- a/packages/edit-post/src/style.scss +++ b/packages/edit-post/src/style.scss @@ -7,7 +7,6 @@ @import "./components/layout/style.scss"; @import "./components/block-manager/style.scss"; @import "./components/meta-boxes/meta-boxes-area/style.scss"; -@import "./components/preferences-modal/style.scss"; @import "./components/secondary-sidebar/style.scss"; @import "./components/sidebar/style.scss"; @import "./components/sidebar/last-revision/style.scss"; From 6693c055af5031a9fd823e468762d85ace2e8dba Mon Sep 17 00:00:00 2001 From: Dominik Schilling Date: Wed, 9 Mar 2022 12:47:39 +0100 Subject: [PATCH 09/17] Post Terms: Unescape HTML entities in term names (#39216) --- packages/block-library/src/post-terms/edit.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/block-library/src/post-terms/edit.js b/packages/block-library/src/post-terms/edit.js index 5496447bc0e990..b5699c008df42f 100644 --- a/packages/block-library/src/post-terms/edit.js +++ b/packages/block-library/src/post-terms/edit.js @@ -2,6 +2,7 @@ * External dependencies */ import classnames from 'classnames'; +import { unescape } from 'lodash'; /** * WordPress dependencies @@ -88,7 +89,7 @@ export default function PostTermsEdit( { href={ postTerm.link } onClick={ ( event ) => event.preventDefault() } > - { postTerm.name } + { unescape( postTerm.name ) } ) ) .reduce( ( prev, curr ) => ( From be119ed071da116476a95aa3d38617c0988aa7e0 Mon Sep 17 00:00:00 2001 From: George Mamadashvili Date: Wed, 9 Mar 2022 12:48:26 +0000 Subject: [PATCH 10/17] Media & Text: Display media while uploading (#39275) --- packages/block-library/src/media-text/edit.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/block-library/src/media-text/edit.js b/packages/block-library/src/media-text/edit.js index 9a6de07a5caf10..9807e9418fb417 100644 --- a/packages/block-library/src/media-text/edit.js +++ b/packages/block-library/src/media-text/edit.js @@ -29,6 +29,7 @@ import { ExternalLink, FocalPointPicker, } from '@wordpress/components'; +import { isBlobURL, getBlobTypeByURL } from '@wordpress/blob'; import { pullLeft, pullRight } from '@wordpress/icons'; import { store as coreStore } from '@wordpress/core-data'; @@ -85,6 +86,10 @@ function attributesFromMedia( { return; } + if ( isBlobURL( media.url ) ) { + media.type = getBlobTypeByURL( media.url ); + } + let mediaType; let src; // For media selections originated from a file upload. From 8721a004f76309e265579e835231bb1dca33f02d Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Wed, 9 Mar 2022 21:20:45 +0800 Subject: [PATCH 11/17] Add some back compat into disableSiteEditorWelcomeGuide (#39300) --- packages/e2e-test-utils/src/site-editor.js | 68 ++++++++++++++++------ 1 file changed, 50 insertions(+), 18 deletions(-) diff --git a/packages/e2e-test-utils/src/site-editor.js b/packages/e2e-test-utils/src/site-editor.js index 0f7bfcc980d059..c86cef72bf45f5 100644 --- a/packages/e2e-test-utils/src/site-editor.js +++ b/packages/e2e-test-utils/src/site-editor.js @@ -59,33 +59,65 @@ export async function closeSiteEditorNavigationPanel() { * Skips the welcome guide popping up to first time users of the site editor */ export async function disableSiteEditorWelcomeGuide() { - const isWelcomeGuideActive = await page.evaluate( - () => - !! wp.data - .select( 'core/preferences' ) - .get( 'core/edit-site', 'welcomeGuide' ) - ); - const isWelcomeGuideStyesActive = await page.evaluate( - () => - !! wp.data - .select( 'core/preferences' ) - .get( 'core/edit-site', 'welcomeGuideStyles' ) - ); + // This code prioritizes using the preferences store. However, performance + // tests run on older versions of the codebase where the preferences store + // doesn't exist. Some backwards compatibility has been built-in so that + // those tests continue to work there. This can be removed once WordPress + // 6.0 is released, as the older version used by the performance tests will + // then include the preferences store. + // See https://github.com/WordPress/gutenberg/pull/39300. + const isWelcomeGuideActive = await page.evaluate( () => { + // TODO - remove if statement after WordPress 6.0 is released. + if ( ! wp.data.select( 'core/preferences' ) ) { + return wp.data + .select( 'core/edit-site' ) + .isFeatureActive( 'welcomeGuide' ); + } + + return !! wp.data + .select( 'core/preferences' ) + ?.get( 'core/edit-site', 'welcomeGuide' ); + } ); + const isWelcomeGuideStyesActive = await page.evaluate( () => { + // TODO - remove if statement after WordPress 6.0 is released. + if ( ! wp.data.select( 'core/preferences' ) ) { + return wp.data + .select( 'core/edit-site' ) + .isFeatureActive( 'welcomeGuideStyles' ); + } + + return !! wp.data + .select( 'core/preferences' ) + ?.get( 'core/edit-site', 'welcomeGuideStyles' ); + } ); if ( isWelcomeGuideActive ) { - await page.evaluate( () => + await page.evaluate( () => { + // TODO - remove if statement after WordPress 6.0 is released. + if ( ! wp.data.dispatch( 'core/preferences' ) ) { + wp.data + .dispatch( 'core/edit-site' ) + .toggleFeature( 'welcomeGuide' ); + } + wp.data .dispatch( 'core/preferences' ) - .toggle( 'core/edit-site', 'welcomeGuide' ) - ); + .toggle( 'core/edit-site', 'welcomeGuide' ); + } ); } if ( isWelcomeGuideStyesActive ) { - await page.evaluate( () => + await page.evaluate( () => { + // TODO - remove if statement after WordPress 6.0 is released. + if ( ! wp.data.dispatch( 'core/preferences' ) ) { + wp.data + .dispatch( 'core/edit-site' ) + .toggleFeature( 'welcomeGuideStyles' ); + } wp.data .dispatch( 'core/preferences' ) - .toggle( 'core/edit-site', 'welcomeGuideStyles' ) - ); + .toggle( 'core/edit-site', 'welcomeGuideStyles' ); + } ); } } From 9973fdabaa49a0ea46c8c50ff52ca3d1c02c1863 Mon Sep 17 00:00:00 2001 From: Siobhan Bamber Date: Wed, 9 Mar 2022 13:24:07 +0000 Subject: [PATCH 12/17] [RNMobile] Small refinements to upload error message (#38951) This PR includes a couple of small refinements to upload errors that display within media upload blocks. Those refinements include the following: 1. Updated copy from `Failed to insert media. Please tap for options.` to `Failed to insert media. Tap for more info.` The purpose of this change is to make it clearer that a more verbose, specific error message can be found by tapping on the failed upload. 2. Text centred. Note, this is tricky to notice, given that the sentences are similar in length, but the text was previously left aligned. This PR updates the text to be centred. --- .../src/components/media-upload-progress/index.native.js | 2 +- packages/block-library/src/file/style.native.scss | 1 + packages/block-library/src/media-text/style.native.scss | 1 + packages/block-library/src/video/style.native.scss | 1 + packages/components/src/mobile/image/style.native.scss | 1 + packages/react-native-editor/CHANGELOG.md | 5 ++--- 6 files changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/block-editor/src/components/media-upload-progress/index.native.js b/packages/block-editor/src/components/media-upload-progress/index.native.js index 003ab5408f15d6..b64b08eec09d8f 100644 --- a/packages/block-editor/src/components/media-upload-progress/index.native.js +++ b/packages/block-editor/src/components/media-upload-progress/index.native.js @@ -122,7 +122,7 @@ export class MediaUploadProgress extends Component { const progress = this.state.progress * 100; // eslint-disable-next-line @wordpress/i18n-no-collapsible-whitespace const retryMessage = __( - 'Failed to insert media.\nPlease tap for options.' + 'Failed to insert media.\nTap for more info.' ); const progressBarStyle = [ diff --git a/packages/block-library/src/file/style.native.scss b/packages/block-library/src/file/style.native.scss index b8c0ad728ca459..0cd3942e158f3f 100644 --- a/packages/block-library/src/file/style.native.scss +++ b/packages/block-library/src/file/style.native.scss @@ -26,6 +26,7 @@ color: #fff; font-size: 14; margin-top: 5; + text-align: center; } .retryContainer { diff --git a/packages/block-library/src/media-text/style.native.scss b/packages/block-library/src/media-text/style.native.scss index 8d909243dcb741..07b584059203ed 100644 --- a/packages/block-library/src/media-text/style.native.scss +++ b/packages/block-library/src/media-text/style.native.scss @@ -116,6 +116,7 @@ $media-to-text: 12px; color: #fff; font-size: 14; margin-top: 5; + text-align: center; } .uploadFailedTextVideo { diff --git a/packages/block-library/src/video/style.native.scss b/packages/block-library/src/video/style.native.scss index dc59037bc3d1d8..153e2799f36ad8 100644 --- a/packages/block-library/src/video/style.native.scss +++ b/packages/block-library/src/video/style.native.scss @@ -31,6 +31,7 @@ color: $gray-dark; font-size: 14; margin-top: 5; + text-align: center; } .modalIcon { diff --git a/packages/components/src/mobile/image/style.native.scss b/packages/components/src/mobile/image/style.native.scss index 96cb68d5319237..c5ccd195993519 100644 --- a/packages/components/src/mobile/image/style.native.scss +++ b/packages/components/src/mobile/image/style.native.scss @@ -89,6 +89,7 @@ color: #fff; font-size: 14; margin-top: 5; + text-align: center; } .editContainer { diff --git a/packages/react-native-editor/CHANGELOG.md b/packages/react-native-editor/CHANGELOG.md index c0ee985bf7d97b..4374cc83ac8939 100644 --- a/packages/react-native-editor/CHANGELOG.md +++ b/packages/react-native-editor/CHANGELOG.md @@ -10,10 +10,9 @@ For each user feature we should also add a importance categorization label to i --> ## Unreleased -- [*] Add GIF badge for animated GIFs uploaded to Image blocks [#38996] - -- [*] Fix autocorrected Headings applying bold formatting on iOS [#38633] +- [*] Add GIF badge for animated GIFs uploaded to Image blocks [#38996] +- [*] Small refinement to media upload errors, including centring and tweaking copy. [#38951] - [*] Update gesture handler and reanimated libraries [#39098] ## 1.71.3 From 802adbde29f15df8e8d2ae85f33e2b210985e1c9 Mon Sep 17 00:00:00 2001 From: Brian Alexander <824344+ironprogrammer@users.noreply.github.com> Date: Wed, 9 Mar 2022 06:06:15 -0800 Subject: [PATCH 13/17] Raise z-index of content div relative to sidebars (#38893) --- packages/base-styles/_z-index.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/base-styles/_z-index.scss b/packages/base-styles/_z-index.scss index 998ea57c7d6c80..457f6bdd229f1c 100644 --- a/packages/base-styles/_z-index.scss +++ b/packages/base-styles/_z-index.scss @@ -33,7 +33,7 @@ $z-layers: ( ".block-editor-url-input__suggestions": 30, ".edit-post-layout__footer": 30, ".interface-interface-skeleton__header": 30, - ".interface-interface-skeleton__content": 20, + ".interface-interface-skeleton__content": 91, ".edit-site-header": 62, ".edit-widgets-header": 30, ".block-library-button__inline-link .block-editor-url-input__suggestions": 6, // URL suggestions for button block above sibling inserter From 848db705d6436bc267234910eb653968e6bf2893 Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Wed, 9 Mar 2022 08:00:42 -0700 Subject: [PATCH 14/17] Fix default duotone preset SVG and style generation (#38681) --- .../theme-json-reference/theme-json-living.md | 1 + .../wordpress-5.9/class-wp-theme-json-5-9.php | 208 ++++++++++-------- .../class-wp-theme-json-resolver-5-9.php | 3 + .../wordpress-5.9/render-svg-filters.php | 62 +++--- lib/compat/wordpress-5.9/theme.json | 17 +- .../get-global-styles-and-settings.php | 66 +++--- packages/block-editor/src/hooks/duotone.js | 30 ++- schemas/json/theme.json | 7 +- 8 files changed, 221 insertions(+), 173 deletions(-) diff --git a/docs/reference-guides/theme-json-reference/theme-json-living.md b/docs/reference-guides/theme-json-reference/theme-json-living.md index ac2d059a1aa0f7..fd4c9c7113900b 100644 --- a/docs/reference-guides/theme-json-reference/theme-json-living.md +++ b/docs/reference-guides/theme-json-reference/theme-json-living.md @@ -45,6 +45,7 @@ Settings related to colors. | custom | boolean | true | | | customDuotone | boolean | true | | | customGradient | boolean | true | | +| defaultDuotone | boolean | true | | | defaultGradients | boolean | true | | | defaultPalette | boolean | true | | | duotone | array | | colors, name, slug | diff --git a/lib/compat/wordpress-5.9/class-wp-theme-json-5-9.php b/lib/compat/wordpress-5.9/class-wp-theme-json-5-9.php index 76bc1c8b4077ad..5ad476b7d13bbf 100644 --- a/lib/compat/wordpress-5.9/class-wp-theme-json-5-9.php +++ b/lib/compat/wordpress-5.9/class-wp-theme-json-5-9.php @@ -69,79 +69,93 @@ class WP_Theme_JSON_5_9 { * * This contains the necessary metadata to process them: * - * - path => where to find the preset within the settings section - * - override => whether a theme preset with the same slug as a default preset - * can override it - * - value_key => the key that represents the value - * - value_func => optionally, instead of value_key, a function to generate - * the value that takes a preset as an argument - * (either value_key or value_func should be present) - * - css_vars => template string to use in generating the CSS Custom Property. - * Example output: "--wp--preset--duotone--blue: " will generate as many CSS Custom Properties as presets defined - * substituting the $slug for the slug's value for each preset value. - * - classes => array containing a structure with the classes to - * generate for the presets, where for each array item - * the key is the class name and the value the property name. - * The "$slug" substring will be replaced by the slug of each preset. - * For example: - * 'classes' => array( - * '.has-$slug-color' => 'color', - * '.has-$slug-background-color' => 'background-color', - * '.has-$slug-border-color' => 'border-color', - * ) - * - properties => array of CSS properties to be used by kses to - * validate the content of each preset - * by means of the remove_insecure_properties method. + * - path => Where to find the preset within the settings section. + * - prevent_override => Whether a theme preset with the same slug as a default preset + * should not override it or the path to a setting for the same + * When defaults. + * The relationship between whether to override the defaults + * and whether the defaults are enabled is inverse: + * - If defaults are enabled => theme presets should not be overriden + * - If defaults are disabled => theme presets should be overriden + * For example, a theme sets defaultPalette to false, + * making the default palette hidden from the user. + * In that case, we want all the theme presets to be present, + * so they should override the defaults by setting this false. + * - value_key => the key that represents the value + * - value_func => optionally, instead of value_key, a function to generate + * the value that takes a preset as an argument + * (either value_key or value_func should be present) + * - css_vars => template string to use in generating the CSS Custom Property. + * Example output: "--wp--preset--duotone--blue: " will generate as many CSS Custom Properties as presets defined + * substituting the $slug for the slug's value for each preset value. + * - classes => array containing a structure with the classes to + * generate for the presets, where for each array item + * the key is the class name and the value the property name. + * The "$slug" substring will be replaced by the slug of each preset. + * For example: + * 'classes' => array( + * '.has-$slug-color' => 'color', + * '.has-$slug-background-color' => 'background-color', + * '.has-$slug-border-color' => 'border-color', + * ) + * - properties => array of CSS properties to be used by kses to + * validate the content of each preset + * by means of the remove_insecure_properties method. */ const PRESETS_METADATA = array( array( - 'path' => array( 'color', 'palette' ), - 'override' => array( 'color', 'defaultPalette' ), - 'use_default_names' => false, - 'value_key' => 'color', - 'css_vars' => '--wp--preset--color--$slug', - 'classes' => array( + 'path' => array( 'color', 'palette' ), + 'prevent_override' => array( 'color', 'defaultPalette' ), + 'use_default_presets' => array( 'color', 'defaultPalette' ), + 'use_default_names' => false, + 'value_key' => 'color', + 'css_vars' => '--wp--preset--color--$slug', + 'classes' => array( '.has-$slug-color' => 'color', '.has-$slug-background-color' => 'background-color', '.has-$slug-border-color' => 'border-color', ), - 'properties' => array( 'color', 'background-color', 'border-color' ), + 'properties' => array( 'color', 'background-color', 'border-color' ), ), array( - 'path' => array( 'color', 'gradients' ), - 'override' => array( 'color', 'defaultGradients' ), - 'use_default_names' => false, - 'value_key' => 'gradient', - 'css_vars' => '--wp--preset--gradient--$slug', - 'classes' => array( '.has-$slug-gradient-background' => 'background' ), - 'properties' => array( 'background' ), + 'path' => array( 'color', 'gradients' ), + 'prevent_override' => array( 'color', 'defaultGradients' ), + 'use_default_presets' => array( 'color', 'defaultGradients' ), + 'use_default_names' => false, + 'value_key' => 'gradient', + 'css_vars' => '--wp--preset--gradient--$slug', + 'classes' => array( '.has-$slug-gradient-background' => 'background' ), + 'properties' => array( 'background' ), ), array( - 'path' => array( 'color', 'duotone' ), - 'override' => true, - 'use_default_names' => false, - 'value_func' => 'gutenberg_get_duotone_filter_property', - 'css_vars' => '--wp--preset--duotone--$slug', - 'classes' => array(), - 'properties' => array( 'filter' ), + 'path' => array( 'color', 'duotone' ), + 'prevent_override' => array( 'color', 'defaultDuotone' ), + 'use_default_presets' => array( 'color', 'defaultDuotone' ), + 'use_default_names' => false, + 'value_func' => 'gutenberg_get_duotone_filter_property', + 'css_vars' => '--wp--preset--duotone--$slug', + 'classes' => array(), + 'properties' => array( 'filter' ), ), array( - 'path' => array( 'typography', 'fontSizes' ), - 'override' => true, - 'use_default_names' => true, - 'value_key' => 'size', - 'css_vars' => '--wp--preset--font-size--$slug', - 'classes' => array( '.has-$slug-font-size' => 'font-size' ), - 'properties' => array( 'font-size' ), + 'path' => array( 'typography', 'fontSizes' ), + 'prevent_override' => false, + 'use_default_presets' => true, + 'use_default_names' => true, + 'value_key' => 'size', + 'css_vars' => '--wp--preset--font-size--$slug', + 'classes' => array( '.has-$slug-font-size' => 'font-size' ), + 'properties' => array( 'font-size' ), ), array( - 'path' => array( 'typography', 'fontFamilies' ), - 'override' => true, - 'use_default_names' => false, - 'value_key' => 'fontFamily', - 'css_vars' => '--wp--preset--font-family--$slug', - 'classes' => array( '.has-$slug-font-family' => 'font-family' ), - 'properties' => array( 'font-family' ), + 'path' => array( 'typography', 'fontFamilies' ), + 'prevent_override' => false, + 'use_default_presets' => true, + 'use_default_names' => false, + 'value_key' => 'fontFamily', + 'css_vars' => '--wp--preset--font-family--$slug', + 'classes' => array( '.has-$slug-font-family' => 'font-family' ), + 'properties' => array( 'font-family' ), ), ); @@ -229,6 +243,7 @@ class WP_Theme_JSON_5_9 { 'custom' => null, 'customDuotone' => null, 'customGradient' => null, + 'defaultDuotone' => null, 'defaultGradients' => null, 'defaultPalette' => null, 'duotone' => null, @@ -1021,9 +1036,14 @@ protected static function scope_selector( $scope, $selector ) { protected static function get_settings_values_by_slug( $settings, $preset_metadata, $origins ) { $preset_per_origin = _wp_array_get( $settings, $preset_metadata['path'], array() ); + $skip_default_presets = ! static::get_metadata_boolean( $settings, $preset_metadata['use_default_presets'], true ); + $result = array(); foreach ( $origins as $origin ) { - if ( ! isset( $preset_per_origin[ $origin ] ) ) { + if ( + ! isset( $preset_per_origin[ $origin ] ) || + ( 'default' === $origin && $skip_default_presets ) + ) { continue; } foreach ( $preset_per_origin[ $origin ] as $preset ) { @@ -1065,9 +1085,14 @@ protected static function get_settings_slugs( $settings, $preset_metadata, $orig $preset_per_origin = _wp_array_get( $settings, $preset_metadata['path'], array() ); + $skip_default_presets = ! static::get_metadata_boolean( $settings, $preset_metadata['use_default_presets'], true ); + $result = array(); foreach ( $origins as $origin ) { - if ( ! isset( $preset_per_origin[ $origin ] ) ) { + if ( + ! isset( $preset_per_origin[ $origin ] ) || + ( 'default' === $origin && $skip_default_presets ) + ) { continue; } foreach ( $preset_per_origin[ $origin ] as $preset ) { @@ -1470,7 +1495,7 @@ public function merge( $incoming ) { // Replace the presets. foreach ( static::PRESETS_METADATA as $preset ) { - $override_preset = static::should_override_preset( $this->theme_json, $node['path'], $preset['override'] ); + $override_preset = ! static::get_metadata_boolean( $this->theme_json['settings'], $preset['prevent_override'], true ); foreach ( static::VALID_ORIGINS as $origin ) { $base_path = array_merge( $node['path'], $preset['path'] ); @@ -1517,6 +1542,7 @@ public function get_svg_filters( $origins ) { $blocks_metadata = static::get_blocks_metadata(); $setting_nodes = static::get_setting_nodes( $this->theme_json, $blocks_metadata ); + $filters = ''; foreach ( $setting_nodes as $metadata ) { $node = _wp_array_get( $this->theme_json, $metadata['path'], array() ); if ( empty( $node['color']['duotone'] ) ) { @@ -1525,9 +1551,11 @@ public function get_svg_filters( $origins ) { $duotone_presets = $node['color']['duotone']; - $filters = ''; foreach ( $origins as $origin ) { - if ( ! isset( $duotone_presets[ $origin ] ) ) { + if ( + ! isset( $duotone_presets[ $origin ] ) || + ( 'default' === $origin && false === $node['color']['defaultDuotone'] ) + ) { continue; } foreach ( $duotone_presets[ $origin ] as $duotone_preset ) { @@ -1540,42 +1568,40 @@ public function get_svg_filters( $origins ) { } /** - * Returns whether a presets should be overriden or not. + * For metadata values that can either be booleans or paths to booleans, gets the value. + * + * ```php + * $data = array( + * 'color' => array( + * 'defaultPalette' => true + * ) + * ); + * + * static::get_metadata_boolean( $data, false ); + * // => false + * + * static::get_metadata_boolean( $data, array( 'color', 'defaultPalette' ) ); + * // => true + * ``` * - * @param array $theme_json The theme.json like structure to inspect. - * @param array $path Path to inspect. - * @param bool|array $override Data to compute whether to override the preset. + * @param array $data The data to inspect. + * @param bool|array $path Boolean or path to a boolean. + * @param bool $default Default value if the referenced path is missing. * @return boolean */ - protected static function should_override_preset( $theme_json, $path, $override ) { - if ( is_bool( $override ) ) { - return $override; + protected static function get_metadata_boolean( $data, $path, $default = false ) { + if ( is_bool( $path ) ) { + return $path; } - // The relationship between whether to override the defaults - // and whether the defaults are enabled is inverse: - // - // - If defaults are enabled => theme presets should not be overriden - // - If defaults are disabled => theme presets should be overriden - // - // For example, a theme sets defaultPalette to false, - // making the default palette hidden from the user. - // In that case, we want all the theme presets to be present, - // so they should override the defaults. - if ( is_array( $override ) ) { - $value = _wp_array_get( $theme_json, array_merge( $path, $override ) ); + if ( is_array( $path ) ) { + $value = _wp_array_get( $data, $path ); if ( isset( $value ) ) { - return ! $value; + return $value; } - - // Search the top-level key if none was found for this node. - $value = _wp_array_get( $theme_json, array_merge( array( 'settings' ), $override ) ); - if ( isset( $value ) ) { - return ! $value; - } - - return true; } + + return $default; } /** diff --git a/lib/compat/wordpress-5.9/class-wp-theme-json-resolver-5-9.php b/lib/compat/wordpress-5.9/class-wp-theme-json-resolver-5-9.php index c16f64f46cee6d..7973810d33f65f 100644 --- a/lib/compat/wordpress-5.9/class-wp-theme-json-resolver-5-9.php +++ b/lib/compat/wordpress-5.9/class-wp-theme-json-resolver-5-9.php @@ -190,6 +190,9 @@ public static function get_theme_data( $deprecated = array() ) { $default_gradients = true; } $theme_support_data['settings']['color']['defaultGradients'] = $default_gradients; + + // Classic themes without a theme.json don't support global duotone. + $theme_support_data['settings']['color']['defaultDuotone'] = false; } $with_theme_supports = new WP_Theme_JSON_Gutenberg( $theme_support_data ); $with_theme_supports->merge( static::$theme ); diff --git a/lib/compat/wordpress-5.9/render-svg-filters.php b/lib/compat/wordpress-5.9/render-svg-filters.php index 8d842c7e79fcc0..f13502b867fe95 100644 --- a/lib/compat/wordpress-5.9/render-svg-filters.php +++ b/lib/compat/wordpress-5.9/render-svg-filters.php @@ -5,44 +5,34 @@ * @package gutenberg */ -/* - * If wp_global_styles_render_svg_filters is defined, it means the plugin - * is running on WordPress 5.9.1, so don't need to render the global styles - * SVG filters as it was already done by WordPress core. +/** + * Render the SVG filters supplied by theme.json. + * + * Note that this doesn't render the per-block user-defined + * filters which are handled by wp_render_duotone_support, + * but it should be rendered before the filtered content + * in the body to satisfy Safari's rendering quirks. */ -if ( ! function_exists( 'wp_global_styles_render_svg_filters' ) ) { - /** - * Render the SVG filters supplied by theme.json. - * - * Note that this doesn't render the per-block user-defined - * filters which are handled by wp_render_duotone_support, - * but it should be rendered before the filtered content - * in the body to satisfy Safari's rendering quirks. +function gutenberg_global_styles_render_svg_filters() { + /* + * When calling via the in_admin_header action, we only want to render the + * SVGs on block editor pages. */ - function wp_global_styles_render_svg_filters() { - /* - * When calling via the in_admin_header action, we only want to render the - * SVGs on block editor pages. - */ - if ( - is_admin() && - ! get_current_screen()->is_block_editor() - ) { - return; - } - - $filters = wp_get_global_styles_svg_filters(); - if ( ! empty( $filters ) ) { - echo $filters; - } + if ( + is_admin() && + ! get_current_screen()->is_block_editor() + ) { + return; } - add_action( - 'wp_body_open', - 'wp_global_styles_render_svg_filters' - ); - add_action( - 'in_admin_header', - 'wp_global_styles_render_svg_filters' - ); + $filters = gutenberg_get_global_styles_svg_filters(); + if ( ! empty( $filters ) ) { + echo $filters; + } } + +// Override actions introduced in 5.9.1 if they exist. +remove_action( 'wp_body_open', 'wp_global_styles_render_svg_filters' ); +remove_action( 'in_admin_header', 'wp_global_styles_render_svg_filters' ); +add_action( 'wp_body_open', 'gutenberg_global_styles_render_svg_filters' ); +add_action( 'in_admin_header', 'gutenberg_global_styles_render_svg_filters' ); diff --git a/lib/compat/wordpress-5.9/theme.json b/lib/compat/wordpress-5.9/theme.json index ec29439d7f13f2..7691aa4a64e6a9 100644 --- a/lib/compat/wordpress-5.9/theme.json +++ b/lib/compat/wordpress-5.9/theme.json @@ -13,46 +13,47 @@ "custom": true, "customDuotone": true, "customGradient": true, + "defaultDuotone": true, "defaultGradients": true, "defaultPalette": true, "duotone": [ { - "name": "Dark grayscale" , + "name": "Dark grayscale", "colors": [ "#000000", "#7f7f7f" ], "slug": "dark-grayscale" }, { - "name": "Grayscale" , + "name": "Grayscale", "colors": [ "#000000", "#ffffff" ], "slug": "grayscale" }, { - "name": "Purple and yellow" , + "name": "Purple and yellow", "colors": [ "#8c00b7", "#fcff41" ], "slug": "purple-yellow" }, { - "name": "Blue and red" , + "name": "Blue and red", "colors": [ "#000097", "#ff4747" ], "slug": "blue-red" }, { - "name": "Midnight" , + "name": "Midnight", "colors": [ "#000000", "#00a5ff" ], "slug": "midnight" }, { - "name": "Magenta and yellow" , + "name": "Magenta and yellow", "colors": [ "#c7005a", "#fff278" ], "slug": "magenta-yellow" }, { - "name": "Purple and green" , + "name": "Purple and green", "colors": [ "#a60072", "#67ff66" ], "slug": "purple-green" }, { - "name": "Blue and orange" , + "name": "Blue and orange", "colors": [ "#1900d8", "#ffa96b" ], "slug": "blue-orange" } diff --git a/lib/compat/wordpress-6.0/get-global-styles-and-settings.php b/lib/compat/wordpress-6.0/get-global-styles-and-settings.php index 5e78029d0d1915..bb8819ec2ef257 100644 --- a/lib/compat/wordpress-6.0/get-global-styles-and-settings.php +++ b/lib/compat/wordpress-6.0/get-global-styles-and-settings.php @@ -134,44 +134,42 @@ function gutenberg_get_global_stylesheet( $types = array() ) { return $stylesheet; } -if ( ! function_exists( 'wp_get_global_styles_svg_filters' ) ) { - /** - * Returns a string containing the SVGs to be referenced as filters (duotone). - * - * @return string - */ - function wp_get_global_styles_svg_filters() { - // Return cached value if it can be used and exists. - // It's cached by theme to make sure that theme switching clears the cache. - $transient_name = 'gutenberg_global_styles_svg_filters_' . get_stylesheet(); - $can_use_cached = ( - ( ! defined( 'WP_DEBUG' ) || ! WP_DEBUG ) && - ( ! defined( 'SCRIPT_DEBUG' ) || ! SCRIPT_DEBUG ) && - ( ! defined( 'REST_REQUEST' ) || ! REST_REQUEST ) && - ! is_admin() - ); - if ( $can_use_cached ) { - $cached = get_transient( $transient_name ); - if ( $cached ) { - return $cached; - } +/** + * Returns a string containing the SVGs to be referenced as filters (duotone). + * + * @return string + */ +function gutenberg_get_global_styles_svg_filters() { + // Return cached value if it can be used and exists. + // It's cached by theme to make sure that theme switching clears the cache. + $transient_name = 'gutenberg_global_styles_svg_filters_' . get_stylesheet(); + $can_use_cached = ( + ( ! defined( 'WP_DEBUG' ) || ! WP_DEBUG ) && + ( ! defined( 'SCRIPT_DEBUG' ) || ! SCRIPT_DEBUG ) && + ( ! defined( 'REST_REQUEST' ) || ! REST_REQUEST ) && + ! is_admin() + ); + if ( $can_use_cached ) { + $cached = get_transient( $transient_name ); + if ( $cached ) { + return $cached; } + } - $supports_theme_json = WP_Theme_JSON_Resolver_Gutenberg::theme_has_support(); - - $origins = array( 'default', 'theme', 'custom' ); - if ( ! $supports_theme_json ) { - $origins = array( 'default' ); - } + $supports_theme_json = WP_Theme_JSON_Resolver_Gutenberg::theme_has_support(); - $tree = WP_Theme_JSON_Resolver_Gutenberg::get_merged_data(); - $svgs = $tree->get_svg_filters( $origins ); + $origins = array( 'default', 'theme', 'custom' ); + if ( ! $supports_theme_json ) { + $origins = array( 'default' ); + } - if ( $can_use_cached ) { - // Cache for a minute, same as gutenberg_get_global_stylesheet. - set_transient( $transient_name, $svgs, MINUTE_IN_SECONDS ); - } + $tree = WP_Theme_JSON_Resolver_Gutenberg::get_merged_data(); + $svgs = $tree->get_svg_filters( $origins ); - return $svgs; + if ( $can_use_cached ) { + // Cache for a minute, same as gutenberg_get_global_stylesheet. + set_transient( $transient_name, $svgs, MINUTE_IN_SECONDS ); } + + return $svgs; } diff --git a/packages/block-editor/src/hooks/duotone.js b/packages/block-editor/src/hooks/duotone.js index 13de8f2a4d79ac..163846d52e415a 100644 --- a/packages/block-editor/src/hooks/duotone.js +++ b/packages/block-editor/src/hooks/duotone.js @@ -12,7 +12,7 @@ import { getBlockSupport, hasBlockSupport } from '@wordpress/blocks'; import { SVG } from '@wordpress/components'; import { createHigherOrderComponent, useInstanceId } from '@wordpress/compose'; import { addFilter } from '@wordpress/hooks'; -import { useContext, createPortal } from '@wordpress/element'; +import { useMemo, useContext, createPortal } from '@wordpress/element'; /** * Internal dependencies @@ -140,12 +140,36 @@ ${ selector } { ); } +function useMultiOriginPresets( { presetSetting, defaultSetting } ) { + const disableDefault = ! useSetting( defaultSetting ); + const userPresets = + useSetting( `${ presetSetting }.custom` ) || EMPTY_ARRAY; + const themePresets = + useSetting( `${ presetSetting }.theme` ) || EMPTY_ARRAY; + const defaultPresets = + useSetting( `${ presetSetting }.default` ) || EMPTY_ARRAY; + return useMemo( + () => [ + ...userPresets, + ...themePresets, + ...( disableDefault ? EMPTY_ARRAY : defaultPresets ), + ], + [ disableDefault, userPresets, themePresets, defaultPresets ] + ); +} + function DuotonePanel( { attributes, setAttributes } ) { const style = attributes?.style; const duotone = style?.color?.duotone; - const duotonePalette = useSetting( 'color.duotone' ) || EMPTY_ARRAY; - const colorPalette = useSetting( 'color.palette' ) || EMPTY_ARRAY; + const duotonePalette = useMultiOriginPresets( { + presetSetting: 'color.duotone', + defaultSetting: 'color.defaultDuotone', + } ); + const colorPalette = useMultiOriginPresets( { + presetSetting: 'color.palette', + defaultSetting: 'color.defaultPalette', + } ); const disableCustomColors = ! useSetting( 'color.custom' ); const disableCustomDuotone = ! useSetting( 'color.customDuotone' ) || diff --git a/schemas/json/theme.json b/schemas/json/theme.json index a21710fe4626b5..f2d8419f281db2 100644 --- a/schemas/json/theme.json +++ b/schemas/json/theme.json @@ -73,6 +73,11 @@ "type": "boolean", "default": true }, + "defaultDuotone": { + "description": "Allow users to choose filters from the default duotone filter presets.", + "type": "boolean", + "default": true + }, "defaultGradients": { "description": "Allow users to choose colors from the default gradients.", "type": "boolean", @@ -642,7 +647,7 @@ } }, "patternProperties": { - "^[a-z][a-z0-9-]*\/[a-z][a-z0-9-]*$": { + "^[a-z][a-z0-9-]*/[a-z][a-z0-9-]*$": { "$ref": "#/definitions/settingsPropertiesComplete" } }, From 39333d427000e3b7dcff16da842a14c109abc844 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Greg=20Zi=C3=B3=C5=82kowski?= Date: Wed, 9 Mar 2022 16:02:15 +0100 Subject: [PATCH 15/17] Packages: Automate npm publishing as part of Gutenberg release workflow (#39259) * Packages: Apply changes to npm publishing workflow * Extend plugin release workflow with npm publishing * Set test npm publishing workflow to trigger when Gutenberg RC1 is out * Update documentation with the reasoning behind Gutenberg plugin sync --- .../upload-release-to-plugin-repo.yml | 39 +++++++++++++ bin/plugin/cli.js | 7 +++ bin/plugin/commands/packages.js | 55 +++++++++++++------ docs/contributors/code/release.md | 34 +++++------- 4 files changed, 98 insertions(+), 37 deletions(-) diff --git a/.github/workflows/upload-release-to-plugin-repo.yml b/.github/workflows/upload-release-to-plugin-repo.yml index 59cfed85c1b8f5..4b7863368eb9b8 100644 --- a/.github/workflows/upload-release-to-plugin-repo.yml +++ b/.github/workflows/upload-release-to-plugin-repo.yml @@ -94,6 +94,45 @@ jobs: name: changelog ${{ matrix.label }} path: ./changelog.txt + npm-publish: + name: Publish WordPress packages to npm + runs-on: ubuntu-latest + needs: update-changelog + if: ${{ github.event.release.prerelease && endsWith( github.event.release.tag_name, '-rc.1' ) && github.event.release.assets[0] }} + steps: + - name: Checkout (for CLI) + uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4 + with: + path: main + ref: trunk + + - name: Checkout (for publishing) + uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4 + with: + path: publish + ref: trunk + token: ${{ secrets.GUTENBERG_TOKEN }} + + - name: Configure git user name and email (for publishing) + run: | + cd publish + git config user.name "Gutenberg Repository Automation" + git config user.email gutenberg@wordpress.org + + - name: Setup Node + uses: actions/setup-node@38d90ce44d5275ad62cc48384b3d8a58c500bb5f # v2.2.2 + with: + node-version: 14 + registry-url: 'https://registry.npmjs.org' + + - name: Publish packages to npm ("next" dist-tag) + run: | + cd main + npm ci + ./bin/plugin/cli.js npm-next --semver minor --ci --repository-path ../publish + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + upload: name: Upload Gutenberg Plugin runs-on: ubuntu-latest diff --git a/bin/plugin/cli.js b/bin/plugin/cli.js index 2227a507e45dca..5ca74a5d9b39da 100755 --- a/bin/plugin/cli.js +++ b/bin/plugin/cli.js @@ -29,12 +29,17 @@ const { runPerformanceTests } = require( './commands/performance' ); const semverOption = [ '--semver ', 'Semantic Versioning', 'patch' ]; const ciOption = [ '-c, --ci', 'Run in CI (non interactive)' ]; +const repositoryPathOption = [ + '--repository-path ', + 'Relative path to the git repository.', +]; program .command( 'publish-npm-packages-latest' ) .alias( 'npm-latest' ) .option( ...semverOption ) .option( ...ciOption ) + .option( ...repositoryPathOption ) .description( 'Publishes packages to npm (latest dist-tag, production version)' ) @@ -45,6 +50,7 @@ program .alias( 'npm-bugfix' ) .option( ...semverOption ) .option( ...ciOption ) + .option( ...repositoryPathOption ) .description( 'Publishes bugfixes for packages to npm (latest dist-tag, production version)' ) @@ -55,6 +61,7 @@ program .alias( 'npm-next' ) .option( ...semverOption ) .option( ...ciOption ) + .option( ...repositoryPathOption ) .description( 'Publishes packages to npm (next dist-tag, prerelease version)' ) diff --git a/bin/plugin/commands/packages.js b/bin/plugin/commands/packages.js index 34f0c9ef864a45..1b070d4eb0ae1f 100644 --- a/bin/plugin/commands/packages.js +++ b/bin/plugin/commands/packages.js @@ -20,6 +20,7 @@ const { runCleanLocalFoldersStep, } = require( './common' ); const git = require( '../lib/git' ); +const { join } = require( 'path' ); /** * Release type names. @@ -36,8 +37,9 @@ const git = require( '../lib/git' ); /** * @typedef WPPackagesCommandOptions * - * @property {SemVer} [semver] The selected semantic versioning. Defaults to `patch`. - * @property {boolean} [ci] Disables interactive mode when executed in CI mode. + * @property {boolean} [ci] Disables interactive mode when executed in CI mode. + * @property {string} [repositoryPath] Relative path to the git repository. + * @property {SemVer} [semver] The selected semantic versioning. Defaults to `patch`. */ /** @@ -331,11 +333,18 @@ async function publishPackagesToNpm( { cwd: gitWorkingDirectoryPath, } ); + log( '>> Current npm user:' ); + await command( 'npm whoami', { + cwd: gitWorkingDirectoryPath, + stdio: 'inherit', + } ); + const beforeCommitHash = await git.getLastCommitHash( gitWorkingDirectoryPath ); const yesFlag = interactive ? '' : '--yes'; + const noVerifyAccessFlag = interactive ? '' : '--no-verify-access'; if ( releaseType === 'next' ) { log( '>> Bumping version of public packages changed since the last release.' @@ -351,7 +360,7 @@ async function publishPackagesToNpm( { log( '>> Publishing modified packages to npm.' ); await command( - `npx lerna publish from-package --dist-tag next ${ yesFlag }`, + `npx lerna publish from-package --dist-tag next ${ yesFlag } ${ noVerifyAccessFlag }`, { cwd: gitWorkingDirectoryPath, stdio: 'inherit', @@ -360,7 +369,7 @@ async function publishPackagesToNpm( { } else if ( releaseType === 'bugfix' ) { log( '>> Publishing modified packages to npm.' ); await command( - `npx lerna publish ${ minimumVersionBump } --no-private ${ yesFlag }`, + `npx lerna publish ${ minimumVersionBump } --no-private ${ yesFlag } ${ noVerifyAccessFlag }`, { cwd: gitWorkingDirectoryPath, stdio: 'inherit', @@ -379,10 +388,13 @@ async function publishPackagesToNpm( { ); log( '>> Publishing modified packages to npm.' ); - await command( `npx lerna publish from-package ${ yesFlag }`, { - cwd: gitWorkingDirectoryPath, - stdio: 'inherit', - } ); + await command( + `npx lerna publish from-package ${ yesFlag } ${ noVerifyAccessFlag }`, + { + cwd: gitWorkingDirectoryPath, + stdio: 'inherit', + } + ); } const afterCommitHash = await git.getLastCommitHash( @@ -458,17 +470,23 @@ async function runPackagesRelease( config, customMessages ) { await askForConfirmation( 'Ready to go?' ); } - // Cloning the Git repository. - config.gitWorkingDirectoryPath = await runGitRepositoryCloneStep( - config.abortMessage - ); - const temporaryFolders = [ config.gitWorkingDirectoryPath ]; + const temporaryFolders = []; + if ( ! config.gitWorkingDirectoryPath ) { + // Cloning the Git repository. + config.gitWorkingDirectoryPath = await runGitRepositoryCloneStep( + config.abortMessage + ); + temporaryFolders.push( config.gitWorkingDirectoryPath ); + } let pluginReleaseBranch; if ( [ 'latest', 'next' ].includes( config.releaseType ) ) { - pluginReleaseBranch = await findPluginReleaseBranchName( - config.gitWorkingDirectoryPath - ); + pluginReleaseBranch = + config.releaseType === 'next' + ? 'trunk' + : await findPluginReleaseBranchName( + config.gitWorkingDirectoryPath + ); await runNpmReleaseBranchSyncStep( pluginReleaseBranch, config ); } else { await checkoutNpmReleaseBranch( config ); @@ -510,10 +528,11 @@ async function runPackagesRelease( config, customMessages ) { * * @return {WPPackagesConfig} The config object. */ -function getConfig( releaseType, { ci, semver } ) { +function getConfig( releaseType, { ci, repositoryPath, semver } ) { return { abortMessage: 'Aborting!', - gitWorkingDirectoryPath: process.cwd(), + gitWorkingDirectoryPath: + repositoryPath && join( process.cwd(), repositoryPath ), interactive: ! ci, minimumVersionBump: semver, npmReleaseBranch: releaseType === 'next' ? 'wp/next' : 'wp/trunk', diff --git a/docs/contributors/code/release.md b/docs/contributors/code/release.md index 53f83b40c84409..1db37c7c6c23ba 100644 --- a/docs/contributors/code/release.md +++ b/docs/contributors/code/release.md @@ -192,27 +192,23 @@ The Gutenberg repository mirrors the [WordPress SVN repository](https://make.wor - The `wp/trunk` branch contains the same version of packages published to npm with the `latest` distribution tag. The WordPress core consumes those packages directly in the `trunk` branch and uses them for public releases. - The `wp/next` branch contains the same version of packages published to npm with the `next` distribution tag. Projects should use those packages for development purposes only. -- A Gutenberg branch targeting a specific WordPress major release (including its further minor increments) is created (example `wp/5.2`) based on the `wp/trunk` Gutenberg branch when the corresponding WordPress release branch is created. (This usually happens when the first `RC` of the next WordPress major version is released). +- A Gutenberg branch targeting a specific WordPress major release (including its further minor increments) is created (example `wp/5.2`) based on the `wp/trunk` Gutenberg branch when the corresponding WordPress release branch is created. (This usually happens when the `beta` or `RC` of the next WordPress major version is released). Release types and their schedule: -- [Synchronizing WordPress Trunk](#synchronizing-wordpress-trunk) (`latest` dist tag) – when there is no "feature-freeze" mode in WordPress Core, publishing happens every two weeks based on the newly created RC1 version of the Gutenberg plugin. Otherwise, only bug fixes get manually included and published to npm before every next beta and RC version of the following WordPress release. -- [Minor WordPress Releases](#minor-wordpress-releases) (`patch` dist tag) – only when bug fixes or security releases need to be backported into WordPress Core. -- [Development Releases](#development-releases) (`next` dist tag) – when there is a "feature-freeze" mode in WordPress Core, publishing can still happen every two weeks based on the new RC1 version of the Gutenberg plugin. It is also possible to perform development releases at any time when there is a need to test the upcoming changes. +- [Synchronizing Gutenberg Plugin](#synchronizing-gutenberg-plugin) (`latest` dist tag) – publishing happens every two weeks based on the newly created RC1 version of the Gutenberg plugin. +- [WordPress Releases](#wordpress-releases) (`patch` dist tag) – only when bug or security fixes need to be backported into WordPress Core. +- [Development Releases](#development-releases) (`next` dist tag) – it is also possible to perform development releases at any time when there is a need to test the upcoming changes. -There is also an option to perform [Standalone Bugfix Package Releases](#standalone-bugfix-package-releases) at will. It should be reserved only for critical bug fixes or security releases that must be published to _npm_ outside of a regular WordPress release cycle. +There is also an option to perform [Standalone Bugfix Package Releases](#standalone-bugfix-package-releases) at will. It should be reserved only for critical bug fixes or security releases that must be published to _npm_ outside of regular cycles. -### Synchronizing WordPress Trunk +### Synchronizing Gutenberg Plugin -For each Gutenberg plugin release, WordPress trunk should be synchronized. +For each Gutenberg plugin release, we also publish to npm an updated version of WordPress packages. This is automated with the [Release Tool](#release-tool) that handles releases for the Gutenberg plugin. -Note that the WordPress `trunk` branch can be closed or in "feature-freeze" mode. Usually, feature freeze in WordPress Core happens about 2 weeks before Beta 1 and remains in effect until RC1 when the `trunk` gets branched. During this period, the Gutenberg plugin releases should not be synchronized with WordPress Core. +We deliberately update the `wp/trunk` branch within the Gutenberg repo with the content from the Gutenberg release `release/*` (example `release/12.7`) branch at the time of the Gutenberg RC1 release. This is done to ensure that the `wp/trunk` branch is as close as possible to the latest version of the Gutenberg plugin. It also practically removes the chances of conflicts while backporting to `trunk` commits with updates applied during publishing to `package.json` and `CHANGELOG.md` files. In the past, we had many issues in that aspect when doing npm publishing after the regular Gutenberg release a week later. When publishing the new package versions to npm, we pick at least the `minor` version bump to account for future bugfix or security releases. -A different person usually synchronizes the WordPress `trunk` branch and publishes the npm packages. Therefore, you typically shouldn't need to worry about handling this for the normal plugin release process. However, if you are still unsure, ask in [the #core-editor Slack channel](https://wordpress.slack.com/archives/C02QB2JS7). - -The process has three steps: 1) update the `wp/trunk` branch within the Gutenberg repo 2) publish the new package versions to npm 3) update the WordPress `trunk` branch. - -All steps are automated via `./bin/plugin/cli.js npm-latest` command. You only have to run the command, but, for the record, the manual process would look very close to the following steps: +All steps are automated via `./bin/plugin/cli.js npm-latest` command. For the record, the manual process would look very close to the following steps: 1. Ensure the WordPress `trunk` branch is open for enhancements. 2. Get the last published Gutenberg release branch with `git fetch`. @@ -220,7 +216,7 @@ All steps are automated via `./bin/plugin/cli.js npm-latest` command. You only h 4. Remove all files from the current branch: `git rm -r .`. 5. Check out all the files from the release branch: `git checkout release/x.x -- .`. 6. Commit all changes to the `wp/trunk` branch with `git commit -m "Merge changes published in the Gutenberg plugin vX.X release"` and push to the repository. -7. Update the `CHANGELOG.md` files of the packages with the new publish version calculated and commit to the `wp/trunk` branch. Assuming the package versions are written using this format `major.minor.patch`, make sure to bump at least the `minor` version number after every major WordPress release. For example, if the CHANGELOG of the package to be released indicates that the next unreleased version is `5.6.1`, choose `5.7.0` as a version in case of `minor` version. This is important as the patch version numbers should be reserved in case bug fixes are needed for a minor WordPress release (see below). +7. Update the `CHANGELOG.md` files of the packages with the new publish version calculated and commit to the `wp/trunk` branch. Assuming the package versions are written using this format `major.minor.patch`, make sure to bump at least the `minor` version bumps gets applied. For example, if the CHANGELOG of the package to be released indicates that the next unreleased version is `5.6.1`, choose `5.7.0` as a version in case of `minor` version. This is important as the patch version numbers should be reserved in case bug fixes are needed for a minor WordPress release (see below). 8. Log-in to npm via the console: `npm login`. Note that you should have 2FA enabled. 9. From the `wp/trunk` branch, install npm dependencies with `npm ci`. 10. Run the script `npm run publish:latest`. @@ -229,11 +225,11 @@ All steps are automated via `./bin/plugin/cli.js npm-latest` command. You only h - If the publishing process ends up incomplete (perhaps because it timed-out or an bad OTP was introduce) you can resume it via [`lerna publish from-package`](https://github.com/lerna/lerna/tree/HEAD/commands/publish#bump-from-package). 11. Finally, now that the npm packages are published, cherry-pick the commits created by lerna ("Publish" and the CHANGELOG update) into the `trunk` branch of Gutenberg. -### Minor WordPress Releases +### WordPress Releases -The following workflow is needed when bug fixes or security releases need to be backported into WordPress Core. This can happen in a few use-cases: +The following workflow is needed when bug or security fixes need to be backported into WordPress Core. This can happen in a few use-cases: -- During the `RC` period of the WordPress release cycle when `wp/X.Y` (example `wp/5.7`) branch for the release is already present. +- During the `beta` and `RC` periods of the WordPress release cycle when `wp/X.Y` (example `wp/5.7`) branch for the release is already present. - For WordPress minor releases and WordPress security releases (example `5.1.1`). 1. Check out the relevant WordPress major branch (If the minor release is 5.2.1, check out `wp/5.2`). @@ -256,7 +252,7 @@ Now, the npm packages should be ready and a patch can be created and committed i ### Standalone Bugfix Package Releases -The following workflow is needed when packages require bug fixes or security releases to be published to _npm_ outside of a regular WordPress release cycle. +The following workflow is needed when packages require bug fixes or security releases to be published to _npm_ outside of a regular release cycle. Note: Both the `trunk` and `wp/trunk` branches are restricted and can only be _pushed_ to by the Gutenberg Core team. @@ -313,7 +309,7 @@ The good news is that the rest of the process is automated with `./bin/plugin/cl ### Development Releases -As noted in the [Synchronizing WordPress Trunk](#synchronizing-wordpress-trunk) section, the WordPress trunk branch can be closed or in "feature-freeze" mode. Usually, this happens during the WordPress ongoing release cycle, which takes several weeks. It means that packages don't get any enhancements and new features during the ongoing WordPress major release process. Another type of release is available to address the limitation mentioned earlier and unblock ongoing development for projects that depend on WordPress packages. We are taking advantage of [package distribution tags](https://docs.npmjs.com/cli/v7/commands/npm-dist-tag) that make it possible to consume the future version of the codebase according to npm guidelines: +As noted in the [Synchronizing Gutenberg Plugin](#synchronizing-gutenberg-plugin) section, packages publishing happens every two weeks from the `wp/trunk` branch. It's also possible to use the development release to test the upcoming changes present in the `trunk` branch at any time. We are taking advantage of [package distribution tags](https://docs.npmjs.com/cli/v7/commands/npm-dist-tag) that make it possible to consume the future version of the codebase according to npm guidelines: > By default, the `latest` tag is used by npm to identify the current version of a package, and `npm install ` (without any `@` or `@` specifier) installs the `latest` tag. Typically, projects only use the `latest` tag for stable release versions, and use other tags for unstable versions such as prereleases. From 8477dc896cf78eb5bc56fced2036c9cc293a5ac5 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation Date: Wed, 9 Mar 2022 16:32:00 +0000 Subject: [PATCH 16/17] Bump plugin version to 12.8.0-rc.1 --- gutenberg.php | 2 +- package-lock.json | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gutenberg.php b/gutenberg.php index 4621513aebbbba..c309eebb42f092 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -5,7 +5,7 @@ * Description: Printing since 1440. This is the development plugin for the new block editor in core. * Requires at least: 5.8 * Requires PHP: 5.6 - * Version: 12.7.1 + * Version: 12.8.0-rc.1 * Author: Gutenberg Team * Text Domain: gutenberg * diff --git a/package-lock.json b/package-lock.json index 89d67a685f5bf6..fab6dbd70bc0e6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "gutenberg", - "version": "12.7.1", + "version": "12.8.0-rc.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 5994b2b5587d20..01cc87dae7598f 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gutenberg", - "version": "12.7.1", + "version": "12.8.0-rc.1", "private": true, "description": "A new WordPress editor experience.", "author": "The WordPress Contributors", From e9994b49786570391b5690b85bd1f1fd78de845e Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation Date: Wed, 9 Mar 2022 17:06:15 +0000 Subject: [PATCH 17/17] Update Changelog for 12.8.0-rc.1 --- changelog.txt | 251 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 251 insertions(+) diff --git a/changelog.txt b/changelog.txt index ba83bcc61d98d8..f6be7949857162 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,256 @@ == Changelog == += 12.8.0-rc.1 = + + + +## Changelog + +### Enhancements + +- Change copying PHP files to dist directory to opt-in via a CLI flag. ([39171](https://github.com/WordPress/gutenberg/pull/39171)) +- Raise z-index of content div relative to sidebars. ([38893](https://github.com/WordPress/gutenberg/pull/38893)) + +#### Components +- Enhance/confirmdialog add custom button text. ([38994](https://github.com/WordPress/gutenberg/pull/38994)) +- InputControl: Allow onBlur for empty values to commit the change, move reset behaviour to ESCAPE key. ([39109](https://github.com/WordPress/gutenberg/pull/39109)) +- Update framer motion to 6.2.8. ([38999](https://github.com/WordPress/gutenberg/pull/38999)) +- `UnitControl`: Tidy up utils and types. ([38987](https://github.com/WordPress/gutenberg/pull/38987)) + +#### Post Editor +- Add interface preferences modal to edit post. ([39176](https://github.com/WordPress/gutenberg/pull/39176)) +- Migrate hidden block types (block manager data) to new preferences packages. ([39132](https://github.com/WordPress/gutenberg/pull/39132)) +- Migrate post editor feature preferences to use new preferences package. ([39115](https://github.com/WordPress/gutenberg/pull/39115)) + +#### Block Library +- Improve create new UI feedback in Nav block. ([39219](https://github.com/WordPress/gutenberg/pull/39219)) +- Media & Text: Display media while uploading. ([39275](https://github.com/WordPress/gutenberg/pull/39275)) + +#### Testing +- Add Home/End keyboard end-to-end test for List View. ([39265](https://github.com/WordPress/gutenberg/pull/39265)) +- Improve switch to draft button end-to-end test robustness. ([38971](https://github.com/WordPress/gutenberg/pull/38971)) + +#### Site Editor +- Migrate site editor to use new preferences package. ([39158](https://github.com/WordPress/gutenberg/pull/39158)) +- Resolve homepage template on server-side. ([38817](https://github.com/WordPress/gutenberg/pull/38817)) + +#### Widgets Editor +- Migrate customize widgets editor to use new preferences package. ([39112](https://github.com/WordPress/gutenberg/pull/39112)) +- Migrate standalone widgets editor to use new preferences package. ([39084](https://github.com/WordPress/gutenberg/pull/39084)) + +#### Media +- MediaReplaceFlow: Add 'onError' prop to handle error notifications. ([39197](https://github.com/WordPress/gutenberg/pull/39197)) + +#### Accessibility +- Block settings dropdown: Use block display title in remove label. ([39110](https://github.com/WordPress/gutenberg/pull/39110)) + +#### Global Styles +- Site Editor: Add theme.json to export file. ([39048](https://github.com/WordPress/gutenberg/pull/39048)) + +#### npm Packages +- Packages: Update CLI publishing tool to run in CI mode. ([38993](https://github.com/WordPress/gutenberg/pull/38993)) + +#### Block Editor +- Add a link completer for inline links to posts. ([29172](https://github.com/WordPress/gutenberg/pull/29172)) + + +### New APIs + +- Add new `@wordpress/preferences` package. ([38873](https://github.com/WordPress/gutenberg/pull/38873)) +- Create Block: Add support for more plugin header fields. ([39096](https://github.com/WordPress/gutenberg/pull/39096)) + + +### Bug Fixes + +- Compose: Avoid memory leak in use-drop-zone. ([39038](https://github.com/WordPress/gutenberg/pull/39038)) +- Fix Global styles overriding block's element styles. ([39012](https://github.com/WordPress/gutenberg/pull/39012)) +- Fix: Button highlight popover overflow conflict with link popover. ([38771](https://github.com/WordPress/gutenberg/pull/38771)) +- Fixes block highlight after block move. ([38915](https://github.com/WordPress/gutenberg/pull/38915)) +- Render SVG props that have dashes correctly. ([38936](https://github.com/WordPress/gutenberg/pull/38936)) +- apiFetch preloading middleware: Handle urlencoded and rest_route query params. ([38914](https://github.com/WordPress/gutenberg/pull/38914)) + +#### Block Library +- Added aria label to the button block with icon. ([38966](https://github.com/WordPress/gutenberg/pull/38966)) +- File: Check if 'fileId' exists before setting the attribute. ([39088](https://github.com/WordPress/gutenberg/pull/39088)) +- File: Don't display loading animation on upload error. ([39213](https://github.com/WordPress/gutenberg/pull/39213)) +- File: Fix the undo trap. ([39215](https://github.com/WordPress/gutenberg/pull/39215)) +- Fix Comments Pagination Number with no pagination settings. ([39204](https://github.com/WordPress/gutenberg/pull/39204)) +- Fix file block validation error by not outputting aria-describedby if there's no description. ([39083](https://github.com/WordPress/gutenberg/pull/39083)) +- Fix navigation menu error when menus are not yet fetched. ([39151](https://github.com/WordPress/gutenberg/pull/39151)) +- Hide border panel when all border features have been disabled. ([36791](https://github.com/WordPress/gutenberg/pull/36791)) +- Hide current menu from dropdown list in Nav block. ([38916](https://github.com/WordPress/gutenberg/pull/38916)) +- Image: Display errors after failed upload. ([39178](https://github.com/WordPress/gutenberg/pull/39178)) +- Media & Text: Display errors after failed upload. ([39245](https://github.com/WordPress/gutenberg/pull/39245)) +- Post Expert: Fix missing class in post excerpt. ([38747](https://github.com/WordPress/gutenberg/pull/38747)) +- Post Terms: Unescape HTML entities in term names. ([39216](https://github.com/WordPress/gutenberg/pull/39216)) +- Restructure code bock styling. ([38712](https://github.com/WordPress/gutenberg/pull/38712)) +- Try: Fix image responsive rules. ([39045](https://github.com/WordPress/gutenberg/pull/39045)) +- Widget Group: Make `save()` markup the same as `render_callback` markup. ([38510](https://github.com/WordPress/gutenberg/pull/38510)) +- [Cover]: Fix keep selected unit on deleting minHeight value. ([39145](https://github.com/WordPress/gutenberg/pull/39145)) + +#### Global Styles +- Fix Blocks list ordering in Global Styles. ([39093](https://github.com/WordPress/gutenberg/pull/39093)) +- Fix default duotone preset SVG and style generation. ([38681](https://github.com/WordPress/gutenberg/pull/38681)) +- [Global Styles]: Fix header panel height. ([39119](https://github.com/WordPress/gutenberg/pull/39119)) + +#### Testing +- Fix performance tests by adding backwards compatibility to welcome guide utility. ([39300](https://github.com/WordPress/gutenberg/pull/39300)) +- e2e-tests: Update preview test to wait for publish panel to appear before closing it. ([39100](https://github.com/WordPress/gutenberg/pull/39100)) + +#### Components +- Update drag gesture of `InputControl`-based controls with axial constraint. ([38968](https://github.com/WordPress/gutenberg/pull/38968)) +- `UnitControl`: Fix controlled `unit` behavior. ([39148](https://github.com/WordPress/gutenberg/pull/39148)) + +#### Post Editor +- Avoid error when 'styles' settings are removed. ([39091](https://github.com/WordPress/gutenberg/pull/39091)) +- URL: Fix code drift in the Editor package by removing duplicate cleanForSlug function. ([39033](https://github.com/WordPress/gutenberg/pull/39033)) + +#### Build Tooling +- Fix `npm run docs:Build` crashing when a `block.json` lacks `supports` key. ([39241](https://github.com/WordPress/gutenberg/pull/39241)) + +#### npm Packages +- Packages: Automatically acceppt all Lerna commands when run with CI flag. ([39199](https://github.com/WordPress/gutenberg/pull/39199)) + +#### CSS & Styling +- Fixes #38761 by removing obsolete `::Before` pseudo element. ([38762](https://github.com/WordPress/gutenberg/pull/38762)) + + +### Documentation + +- Add import useBlockProps. ([39072](https://github.com/WordPress/gutenberg/pull/39072)) +- Docs: Emphasized requirement to enclose in quotation marks wp-env run…. ([39101](https://github.com/WordPress/gutenberg/pull/39101)) +- Spelling error in `JustifyContentControl` example. ([39234](https://github.com/WordPress/gutenberg/pull/39234)) +- [Gutenberg Data Tutorial] Part 3: Building an edit form. ([38581](https://github.com/WordPress/gutenberg/pull/38581)) + +#### Components +- Move recent CHANGELOG entry to `Unreleased` section. ([39169](https://github.com/WordPress/gutenberg/pull/39169)) +- Storybook: Support proper extraction of TypeScript prop types. ([38842](https://github.com/WordPress/gutenberg/pull/38842)) +- fix: Code example in flyout component. ([39156](https://github.com/WordPress/gutenberg/pull/39156)) + + +### Code Quality + +- Core Data: Rename `types` directory to `entity-types`. ([39225](https://github.com/WordPress/gutenberg/pull/39225)) +- Core data: Fix some typing issues. ([39212](https://github.com/WordPress/gutenberg/pull/39212)) +- Core data: Fix some typing issues. ([39214](https://github.com/WordPress/gutenberg/pull/39214)) +- Fix `@wordpress/comment-case` ESlint errors but without adding the disable-rule pragma. ([37006](https://github.com/WordPress/gutenberg/pull/37006)) +- Refactor useSelect usages to useEntityRecords. ([38827](https://github.com/WordPress/gutenberg/pull/38827)) + +#### Post Editor +- useBlockEditorSettings: Remove unused unstableBase fetch. ([39221](https://github.com/WordPress/gutenberg/pull/39221)) + +#### Widgets Editor +- Delete widget editor redundant css for more menu. ([39113](https://github.com/WordPress/gutenberg/pull/39113)) + +#### Plugin +- Layout: Remove duplicate var declaration. ([39111](https://github.com/WordPress/gutenberg/pull/39111)) + +#### Global Styles +- Move editor settings code to compat folder. ([39030](https://github.com/WordPress/gutenberg/pull/39030)) + +#### Themes +- Don't filter 'theme_templates' when running WP 5.9. ([39017](https://github.com/WordPress/gutenberg/pull/39017)) + +#### Components +- TreeGrid: Update callback unit tests to use TreeGridRow and TreeGridCell sub components. ([39002](https://github.com/WordPress/gutenberg/pull/39002)) + +#### Block Library +- Improve Nav block loading and placeholder states. ([38907](https://github.com/WordPress/gutenberg/pull/38907)) + + +### Tools + +- Code owners: Remove users without write access and fix typos. ([39238](https://github.com/WordPress/gutenberg/pull/39238)) +- Simplify Pull Request template. ([39229](https://github.com/WordPress/gutenberg/pull/39229)) + +#### Testing +- Add end-to-end testing for experimental nav menu deletion. ([38955](https://github.com/WordPress/gutenberg/pull/38955)) +- Add test case for post locking feature saving. ([39022](https://github.com/WordPress/gutenberg/pull/39022)) +- Add tests for media replace flow. ([39005](https://github.com/WordPress/gutenberg/pull/39005)) +- Block Test Fixtures: Add additional error message for serialized test fixtures that reserialize identically. ([39039](https://github.com/WordPress/gutenberg/pull/39039)) +- Update 'clickMenuItem' test util to use full label matching. ([39274](https://github.com/WordPress/gutenberg/pull/39274)) + +#### Build Tooling +- Fix spelling of contributors in changelog script. ([39029](https://github.com/WordPress/gutenberg/pull/39029)) +- Resolve peer dependency warnings. ([39043](https://github.com/WordPress/gutenberg/pull/39043)) + +#### npm Packages +- Packages: Automate npm publishing as part of Gutenberg release workflow. ([39259](https://github.com/WordPress/gutenberg/pull/39259)) + + +### Various + +- Add a resolvable JavaScript entry point to base-styles. ([39240](https://github.com/WordPress/gutenberg/pull/39240)) +- Add reusable preferences modal to interface package. ([39153](https://github.com/WordPress/gutenberg/pull/39153)) +- Create Block: Add confirm prompt before showing the plugin options. ([39105](https://github.com/WordPress/gutenberg/pull/39105)) +- Create Block: Improve custom project template configuration. ([39049](https://github.com/WordPress/gutenberg/pull/39049)) +- Element: Add changelog notes for serialize attribute casing. ([39141](https://github.com/WordPress/gutenberg/pull/39141)) +- Missing `,toggleFormat` from last code block. ([39146](https://github.com/WordPress/gutenberg/pull/39146)) +- Remove rename rn UI tests. ([39042](https://github.com/WordPress/gutenberg/pull/39042)) + +#### Block Library +- Adding a GIF badge to image blocks with gifs in them. ([38996](https://github.com/WordPress/gutenberg/pull/38996)) +- Buttons: Don't set a placeholder text color. ([39034](https://github.com/WordPress/gutenberg/pull/39034)) +- Post author name: Add "post" prefix to CSS class. ([38320](https://github.com/WordPress/gutenberg/pull/38320)) +- Post comments form block show warning wrt to post/page. ([38011](https://github.com/WordPress/gutenberg/pull/38011)) +- Refactor classic menu conversion process. ([38858](https://github.com/WordPress/gutenberg/pull/38858)) +- Social Icons - Begin Automating Existing Manual Test Cases. ([39027](https://github.com/WordPress/gutenberg/pull/39027)) +- Tag Cloud: Use flex for the Outline style. ([38995](https://github.com/WordPress/gutenberg/pull/38995)) + +#### Components +- FontSizePicker: Refactor stories to use Controls. ([38727](https://github.com/WordPress/gutenberg/pull/38727)) +- Normalize font-family. ([38969](https://github.com/WordPress/gutenberg/pull/38969)) +- Storybook: Add webpack loader for easier story descriptions. ([39165](https://github.com/WordPress/gutenberg/pull/39165)) +- [Components]: Update changelog follow up for #38985. ([39013](https://github.com/WordPress/gutenberg/pull/39013)) + +#### Themes +- Theme Export: Add index.php and style.css. ([39173](https://github.com/WordPress/gutenberg/pull/39173)) + +#### Icons +- Update Pin icon, add new Post icon. ([39139](https://github.com/WordPress/gutenberg/pull/39139)) + +#### Block Conversion +- [Block Conversion]: Show `group` option in `Group` blocks. ([39094](https://github.com/WordPress/gutenberg/pull/39094)) + +#### Accessibility +- Try allowing tab into block placeholder. ([39085](https://github.com/WordPress/gutenberg/pull/39085)) + +#### Full Site Editing +- Expose plugin area to site editor's List page. ([39078](https://github.com/WordPress/gutenberg/pull/39078)) + +#### Data Layer +- Handle resolution errors in @wordpress/data. ([38669](https://github.com/WordPress/gutenberg/pull/38669)) + +#### Design Tools +- Webfonts API. ([37140](https://github.com/WordPress/gutenberg/pull/37140)) + +#### Global Styles +- Account for upcoming changes in styles metadata in WordPress 5.9. ([36327](https://github.com/WordPress/gutenberg/pull/36327)) + + +## First time contributors + +The following PRs were merged by first time contributors: + +- @ahsanshaheen199: fix: Code example in flyout component. ([39156](https://github.com/WordPress/gutenberg/pull/39156)) +- @alshakerM: Render SVG props that have dashes correctly. ([38936](https://github.com/WordPress/gutenberg/pull/38936)) +- @awps: Missing `,toggleFormat` from last code block. ([39146](https://github.com/WordPress/gutenberg/pull/39146)) +- @francisei: Docs: Emphasized requirement to enclose in quotation marks wp-env run…. ([39101](https://github.com/WordPress/gutenberg/pull/39101)) +- @ironprogrammer: Raise z-index of content div relative to sidebars. ([38893](https://github.com/WordPress/gutenberg/pull/38893)) +- @joshuafredrickson: Add a resolvable JavaScript entry point to base-styles. ([39240](https://github.com/WordPress/gutenberg/pull/39240)) +- @jostnes: Remove rename rn UI tests. ([39042](https://github.com/WordPress/gutenberg/pull/39042)) +- @mashikag: Fix Blocks list ordering in Global Styles. ([39093](https://github.com/WordPress/gutenberg/pull/39093)) +- @tomasztunik: Fix Global styles overriding block's element styles. ([39012](https://github.com/WordPress/gutenberg/pull/39012)) +- @Tumas2: Spelling error in `JustifyContentControl` example. ([39234](https://github.com/WordPress/gutenberg/pull/39234)) + + +## Contributors + +The following contributors merged PRs in this release: + +@adamziel @ahsanshaheen199 @ajlende @alexstine @alshakerM @amustaque97 @andrewserong @aristath @awps @c4rl0sbr4v0 @carolinan @chad1008 @ciampo @delowardev @dmsnell @draganescu @fluiddot @francisei @getdave @gwwar @gziolo @illusaen @ironprogrammer @jasmussen @joshuafredrickson @jostnes @jsnajdr @Mamaduka @mashikag @mirka @ndiego @noahtallen @noisysocks @ntsekouras @oandregal @ocean90 @opr @priethor @ramonjd @ryanwelcher @scruffian @Sidsector9 @SiobhyB @Sisanu @stokesman @talldan @tellthemachines @tomasztunik @ttahmouch @Tumas2 @walbo @webmandesign @zaguiini @ZebulanStanphill + + = 12.7.1 =