From 5deecb29e39f4b7be418b2b384cd263a4ed5546a Mon Sep 17 00:00:00 2001 From: James Koster Date: Mon, 27 May 2024 12:47:12 +0100 Subject: [PATCH 01/15] Inspector: Remove revisions panel (#61867) Co-authored-by: jameskoster Co-authored-by: youknowriad Co-authored-by: ntsekouras --- packages/editor/src/components/post-actions/actions.js | 4 +++- packages/editor/src/components/sidebar/index.js | 2 -- test/e2e/specs/editor/various/footnotes.spec.js | 10 +++++++--- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/packages/editor/src/components/post-actions/actions.js b/packages/editor/src/components/post-actions/actions.js index a4937dc6a75d74..bd7552b642fad7 100644 --- a/packages/editor/src/components/post-actions/actions.js +++ b/packages/editor/src/components/post-actions/actions.js @@ -1108,6 +1108,7 @@ export function usePostActions( postType, onActionPerformed ) { ].includes( postType ); const isPattern = postType === PATTERN_POST_TYPE; const isLoaded = !! postTypeObject; + const supportsRevisions = !! postTypeObject?.supports?.revisions; return useMemo( () => { if ( ! isLoaded ) { return []; @@ -1115,7 +1116,7 @@ export function usePostActions( postType, onActionPerformed ) { const actions = [ postTypeObject?.viewable && viewPostAction, - postRevisionsAction, + supportsRevisions && postRevisionsAction, globalThis.IS_GUTENBERG_PLUGIN ? ! isTemplateOrTemplatePart && ! isPattern && @@ -1181,5 +1182,6 @@ export function usePostActions( postType, onActionPerformed ) { restorePostAction, onActionPerformed, isLoaded, + supportsRevisions, ] ); } diff --git a/packages/editor/src/components/sidebar/index.js b/packages/editor/src/components/sidebar/index.js index 30d27a8c5db306..7a6a1d10282731 100644 --- a/packages/editor/src/components/sidebar/index.js +++ b/packages/editor/src/components/sidebar/index.js @@ -26,7 +26,6 @@ import PageAttributesPanel from '../page-attributes/panel'; import PatternOverridesPanel from '../pattern-overrides-panel'; import PluginDocumentSettingPanel from '../plugin-document-setting-panel'; import PluginSidebar from '../plugin-sidebar'; -import PostLastRevisionPanel from '../post-last-revision/panel'; import PostSummary from './post-summary'; import PostTaxonomiesPanel from '../post-taxonomies/panel'; import PostTransformPanel from '../post-transform-panel'; @@ -117,7 +116,6 @@ const SidebarContent = ( { ) } - diff --git a/test/e2e/specs/editor/various/footnotes.spec.js b/test/e2e/specs/editor/various/footnotes.spec.js index 01017b2d2ea2e6..e7fd3804706471 100644 --- a/test/e2e/specs/editor/various/footnotes.spec.js +++ b/test/e2e/specs/editor/various/footnotes.spec.js @@ -363,11 +363,15 @@ test.describe( 'Footnotes', () => { // Open revisions. await editor.openDocumentSettingsSidebar(); + const editorSettings = page.getByRole( 'region', { + name: 'Editor settings', + } ); + await editorSettings.getByRole( 'tab', { name: 'Post' } ).click(); + await editorSettings.getByRole( 'button', { name: 'Actions' } ).click(); await page - .getByRole( 'region', { name: 'Editor settings' } ) - .getByRole( 'tab', { name: 'Post' } ) + .getByRole( 'menu' ) + .getByRole( 'menuitem', { name: 'View revisions' } ) .click(); - await page.locator( 'a:text("Revisions (2)")' ).click(); await page.locator( '.revisions-controls .ui-slider-handle' ).focus(); await page.keyboard.press( 'ArrowLeft' ); await page.locator( 'input:text("Restore This Revision")' ).click(); From 68ac168afd7cd5ba40063245e1ed580fc76ddb50 Mon Sep 17 00:00:00 2001 From: Tom Cafferkey Date: Mon, 27 May 2024 12:48:50 +0100 Subject: [PATCH 02/15] Navigation block: Check for update_ignored_hooked_blocks_postmeta in core (#61903) Adding another `has_filter` check before adding the Navigation blocks filter to store `ignoredHookedBlocks` metadata as this functionality is being moved into WP core. Co-authored-by: Bernie Reiter <96308+ockham@users.noreply.github.com> --- packages/block-library/src/navigation/index.php | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/block-library/src/navigation/index.php b/packages/block-library/src/navigation/index.php index c5ef8e9204b32d..ba36acf139a626 100644 --- a/packages/block-library/src/navigation/index.php +++ b/packages/block-library/src/navigation/index.php @@ -1617,10 +1617,16 @@ function block_core_navigation_update_ignore_hooked_blocks_meta( $post ) { $rest_insert_wp_navigation_core_callback = 'block_core_navigation_' . 'update_ignore_hooked_blocks_meta'; // phpcs:ignore Generic.Strings.UnnecessaryStringConcat.Found /* - * Injection of hooked blocks into the Navigation block relies on some functions present in WP >= 6.5 - * that are not present in Gutenberg's WP 6.5 compatibility layer. + * Do not add the `block_core_navigation_update_ignore_hooked_blocks_meta` filter in the following cases: + * - If Core has added the `update_ignored_hooked_blocks_postmeta` filter already (WP >= 6.6); + * - or if the `set_ignored_hooked_blocks_metadata` function is unavailable (which is required for the filter to work. It was introduced by WP 6.5 but is not present in Gutenberg's WP 6.5 compatibility layer); + * - or if the `$rest_insert_wp_navigation_core_callback` filter has already been added. */ -if ( function_exists( 'set_ignored_hooked_blocks_metadata' ) && ! has_filter( 'rest_pre_insert_wp_navigation', $rest_insert_wp_navigation_core_callback ) ) { +if ( + ! has_filter( 'rest_pre_insert_wp_navigation', 'update_ignored_hooked_blocks_postmeta' ) && + function_exists( 'set_ignored_hooked_blocks_metadata' ) && + ! has_filter( 'rest_pre_insert_wp_navigation', $rest_insert_wp_navigation_core_callback ) +) { add_filter( 'rest_pre_insert_wp_navigation', 'block_core_navigation_update_ignore_hooked_blocks_meta' ); } From 58b454c05172c51a023e36ff3b7078ee63086e09 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Mon, 27 May 2024 05:01:42 -0700 Subject: [PATCH 03/15] Use output buffer and HTML tag processor to inject directives on BODY tag for full-page client-side navigation (#61212) * Inject client-side navigation directives via Tag Processor and output buffering * Fix typing for render_block phpdoc * Eliminate use of render_block filter * Remove copy-pasta since tag Co-authored-by: dmsnell * Ensure client-side directives are only added to HTML response bodies --------- Co-authored-by: westonruter Co-authored-by: dmsnell Co-authored-by: cbravobernal --- .../full-page-client-side-navigation.php | 70 +++++++++++++++---- 1 file changed, 57 insertions(+), 13 deletions(-) diff --git a/lib/experimental/full-page-client-side-navigation.php b/lib/experimental/full-page-client-side-navigation.php index ebfddf4aaf4369..621502912a668a 100644 --- a/lib/experimental/full-page-client-side-navigation.php +++ b/lib/experimental/full-page-client-side-navigation.php @@ -33,25 +33,69 @@ function _gutenberg_add_enhanced_pagination_to_query_block( $parsed_block ) { add_filter( 'render_block_data', '_gutenberg_add_enhanced_pagination_to_query_block' ); /** - * Add directives to all links. + * Adds client-side navigation directives to BODY tag. * * Note: This should probably be done per site, not by default when this option is enabled. * - * @param array $content The block content. + * @param string $response_body The response body. * - * @return array The same block content with the directives needed. + * @return string The rendered template with modified BODY attributes. */ -function _gutenberg_add_client_side_navigation_directives( $content ) { - $p = new WP_HTML_Tag_Processor( $content ); - // Hack to add the necessary directives to the body tag. - // TODO: Find a proper way to add directives to the body tag. - static $body_interactive_added; - if ( ! $body_interactive_added ) { - $body_interactive_added = true; - return (string) $p . ''; +function _gutenberg_add_client_side_navigation_directives( $response_body ) { + $is_html_content_type = false; + foreach ( headers_list() as $header ) { + $header_parts = preg_split( '/\s*[:;]\s*/', strtolower( $header ) ); + if ( count( $header_parts ) >= 2 && 'content-type' === $header_parts[0] ) { + $is_html_content_type = in_array( $header_parts[1], array( 'text/html', 'application/xhtml+xml' ), true ); + } } - return (string) $p; + if ( ! $is_html_content_type ) { + return $response_body; + } + + $p = new WP_HTML_Tag_Processor( $response_body ); + if ( $p->next_tag( array( 'tag_name' => 'BODY' ) ) ) { + $p->set_attribute( 'data-wp-interactive', 'core/experimental' ); + $p->set_attribute( 'data-wp-context', '{}' ); + $response_body = $p->get_updated_html(); + } + return $response_body; } // TODO: Explore moving this to the server directive processing. -add_filter( 'render_block', '_gutenberg_add_client_side_navigation_directives' ); +add_filter( 'gutenberg_template_output_buffer', '_gutenberg_add_client_side_navigation_directives' ); + +/** + * Starts output buffering at the end of the 'template_include' filter. + * + * This is to implement #43258 in core. + * + * This is a hack which would eventually be replaced with something like this in wp-includes/template-loader.php: + * + * $template = apply_filters( 'template_include', $template ); + * + ob_start( 'wp_template_output_buffer_callback' ); + * if ( $template ) { + * include $template; + * } elseif ( current_user_can( 'switch_themes' ) ) { + * + * @link https://core.trac.wordpress.org/ticket/43258 + * + * @param string $passthrough Value for the template_include filter which is passed through. + * + * @return string Unmodified value of $passthrough. + */ +function _gutenberg_buffer_template_output( string $passthrough ): string { + ob_start( + static function ( string $output ): string { + /** + * Filters the template output buffer prior to sending to the client. + * + * @param string $output Output buffer. + * @return string Filtered output buffer. + */ + return (string) apply_filters( 'gutenberg_template_output_buffer', $output ); + } + ); + return $passthrough; +} +add_filter( 'template_include', '_gutenberg_buffer_template_output', PHP_INT_MAX ); From bd9b1707484e18d0c1c8bd05d693e2ec940385ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Mon, 27 May 2024 14:22:03 +0200 Subject: [PATCH 04/15] Pages sidebar: adds published & scheduled items (#62021) Co-authored-by: oandregal Co-authored-by: ntsekouras --- .../sidebar-dataviews/default-views.js | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/packages/edit-site/src/components/sidebar-dataviews/default-views.js b/packages/edit-site/src/components/sidebar-dataviews/default-views.js index 7610adb006509f..6a10e0cd95d7b3 100644 --- a/packages/edit-site/src/components/sidebar-dataviews/default-views.js +++ b/packages/edit-site/src/components/sidebar-dataviews/default-views.js @@ -54,6 +54,36 @@ export const DEFAULT_VIEWS = { icon: pages, view: DEFAULT_PAGE_BASE, }, + { + title: __( 'Published' ), + slug: 'published', + icon: pages, + view: { + ...DEFAULT_PAGE_BASE, + filters: [ + { + field: 'status', + operator: OPERATOR_IS_ANY, + value: 'publish', + }, + ], + }, + }, + { + title: __( 'Scheduled' ), + slug: 'future', + icon: pages, + view: { + ...DEFAULT_PAGE_BASE, + filters: [ + { + field: 'status', + operator: OPERATOR_IS_ANY, + value: 'future', + }, + ], + }, + }, { title: __( 'Drafts' ), slug: 'drafts', From 85aa9dbba204efe7f0df0755ce01e46925945306 Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Mon, 27 May 2024 15:02:32 +0200 Subject: [PATCH 05/15] Interactivity API: Fix null and number strings as namespaces runtime error. (#61960) * Fix null and number strings as namespaces runtime error * Update with suggestions * Update changelog * added wrong css changes * Revert move isObject to utils * Rename url vars Co-authored-by: cbravobernal Co-authored-by: sirreal --- .../interactive-blocks/namespace/render.php | 22 ++++++++ .../interactive-blocks/namespace/view.js | 56 ++++++++++++++++++- packages/interactivity/CHANGELOG.md | 4 ++ packages/interactivity/src/store.ts | 1 - packages/interactivity/src/vdom.ts | 7 ++- .../e2e/specs/interactivity/namespace.spec.ts | 50 +++++++++++++++-- 6 files changed, 130 insertions(+), 10 deletions(-) diff --git a/packages/e2e-tests/plugins/interactive-blocks/namespace/render.php b/packages/e2e-tests/plugins/interactive-blocks/namespace/render.php index 6fdc2d07e350c8..0b7e40b6c1653b 100644 --- a/packages/e2e-tests/plugins/interactive-blocks/namespace/render.php +++ b/packages/e2e-tests/plugins/interactive-blocks/namespace/render.php @@ -18,6 +18,28 @@ +
+ +
+ +
+ +
+
+ +
+ +
+ +
+ +
+
+ +
+
+ +
diff --git a/packages/e2e-tests/plugins/interactive-blocks/namespace/view.js b/packages/e2e-tests/plugins/interactive-blocks/namespace/view.js index 9225f88ce9d279..5717387395ff24 100644 --- a/packages/e2e-tests/plugins/interactive-blocks/namespace/view.js +++ b/packages/e2e-tests/plugins/interactive-blocks/namespace/view.js @@ -3,9 +3,16 @@ */ import { store } from '@wordpress/interactivity'; + +store( '', { + state: { + url: '/empty-string-url', + }, +} ); + store( 'namespace', { state: { - url: '/some-url', + url: '/namespace-url', }, } ); @@ -14,3 +21,50 @@ store( 'other', { url: '/other-store-url', }, } ); + +store( 'null', { + state: { + url: '/null-url', + }, +} ); + +store( '2', { + state: { + url: '/number-url', + }, +} ); + +store( '{}', { + state: { + url: '/object-url', + }, +} ); + +store( 'true', { + state: { + url: '/true-url', + }, +} ); + +store( 'false', { + state: { + url: '/false-url', + }, +} ); + +store( '[]', { + state: { + url: '/array-url', + }, +} ); + +store( '"quoted string"', { + state: { + url: '/quoted-url', + }, +} ); + + + + + diff --git a/packages/interactivity/CHANGELOG.md b/packages/interactivity/CHANGELOG.md index e40c68a50180a2..c3542b914de159 100644 --- a/packages/interactivity/CHANGELOG.md +++ b/packages/interactivity/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Bug fixes + +- Fix null and number strings as namespaces runtime error. ([#61960](https://github.com/WordPress/gutenberg/pull/61960/)) + ### Breaking Changes - Variables like `process.env.IS_GUTENBERG_PLUGIN` have been replaced by `globalThis.IS_GUTENBERG_PLUGIN`. Build systems using `process.env` should be updated ([#61486](https://github.com/WordPress/gutenberg/pull/61486)). diff --git a/packages/interactivity/src/store.ts b/packages/interactivity/src/store.ts index d173f2cd842dc1..9b35192fe8b132 100644 --- a/packages/interactivity/src/store.ts +++ b/packages/interactivity/src/store.ts @@ -15,7 +15,6 @@ import { setNamespace, resetNamespace, } from './hooks'; - const isObject = ( item: unknown ): item is Record< string, unknown > => Boolean( item && typeof item === 'object' && item.constructor === Object ); diff --git a/packages/interactivity/src/vdom.ts b/packages/interactivity/src/vdom.ts index cc481f89ff772a..98deca656cfa6c 100644 --- a/packages/interactivity/src/vdom.ts +++ b/packages/interactivity/src/vdom.ts @@ -13,6 +13,8 @@ const islandAttr = `data-${ p }-interactive`; const fullPrefix = `data-${ p }-`; const namespaces: Array< string | null > = []; const currentNamespace = () => namespaces[ namespaces.length - 1 ] ?? null; +const isObject = ( item: unknown ): item is Record< string, unknown > => + Boolean( item && typeof item === 'object' && item.constructor === Object ); // Regular expression for directive parsing. const directiveParser = new RegExp( @@ -100,8 +102,9 @@ export function toVdom( root: Node ): Array< ComponentChild > { const namespace = regexResult?.[ 1 ] ?? null; let value: any = regexResult?.[ 2 ] ?? attributeValue; try { - value = value && JSON.parse( value ); - } catch ( e ) {} + const parsedValue = JSON.parse( value ); + value = isObject( parsedValue ) ? parsedValue : value; + } catch {} if ( attributeName === islandAttr ) { island = true; const islandNamespace = diff --git a/test/e2e/specs/interactivity/namespace.spec.ts b/test/e2e/specs/interactivity/namespace.spec.ts index fd38a7ecf6ed64..9d0edc997886cb 100644 --- a/test/e2e/specs/interactivity/namespace.spec.ts +++ b/test/e2e/specs/interactivity/namespace.spec.ts @@ -20,30 +20,68 @@ test.describe( 'Namespaces', () => { test( 'Empty string as namespace should not work', async ( { page } ) => { const el = page.getByTestId( 'empty namespace' ); - await expect( el ).not.toHaveAttribute( 'href', '/some-url' ); + await expect( el ).not.toHaveAttribute( 'href', '/empty-string-url' ); } ); test( 'A string as namespace should work', async ( { page } ) => { const el = page.getByTestId( 'correct namespace' ); - await expect( el ).toHaveAttribute( 'href', '/some-url' ); + await expect( el ).toHaveAttribute( 'href', '/namespace-url' ); } ); - test( 'An empty object as namespace should work', async ( { page } ) => { + test( 'An empty object as namespace should not work', async ( { + page, + } ) => { const el = page.getByTestId( 'object namespace' ); - await expect( el ).not.toHaveAttribute( 'href', '/some-url' ); + await expect( el ).not.toHaveAttribute( 'href', '/object-url' ); } ); test( 'A wrong namespace should not break the runtime', async ( { page, } ) => { const el = page.getByTestId( 'object namespace' ); - await expect( el ).not.toHaveAttribute( 'href', '/some-url' ); + await expect( el ).not.toHaveAttribute( 'href', '/namespace-url' ); const correct = page.getByTestId( 'correct namespace' ); - await expect( correct ).toHaveAttribute( 'href', '/some-url' ); + await expect( correct ).toHaveAttribute( 'href', '/namespace-url' ); } ); test( 'A different store namespace should work', async ( { page } ) => { const el = page.getByTestId( 'other namespace' ); await expect( el ).toHaveAttribute( 'href', '/other-store-url' ); } ); + + test( 'A number as a string as namespace should work', async ( { + page, + } ) => { + const el = page.getByTestId( 'number namespace' ); + await expect( el ).toHaveAttribute( 'href', '/number-url' ); + } ); + + test( 'A null as a string as namespace should work', async ( { page } ) => { + const el = page.getByTestId( 'null namespace' ); + await expect( el ).toHaveAttribute( 'href', '/null-url' ); + } ); + + test( 'A true as a string as namespace should work', async ( { page } ) => { + const el = page.getByTestId( 'true namespace' ); + await expect( el ).toHaveAttribute( 'href', '/true-url' ); + } ); + + test( 'A false as a string as namespace should work', async ( { + page, + } ) => { + const el = page.getByTestId( 'false namespace' ); + await expect( el ).toHaveAttribute( 'href', '/false-url' ); + } ); + + test( 'A [] as a string as namespace should work', async ( { page } ) => { + const el = page.getByTestId( '[] namespace' ); + await expect( el ).toHaveAttribute( 'href', '/array-url' ); + } ); + + test( 'A "quoted string" as a string as namespace should work', async ( { + page, + } ) => { + const el = page.getByTestId( 'quoted namespace' ); + await expect( el ).toHaveAttribute( 'href', '/quoted-url' ); + } ); } ); From 2b94b3b5b28c5ea22a36d358f926cf98212bfa83 Mon Sep 17 00:00:00 2001 From: Dani Guardiola Date: Mon, 27 May 2024 15:07:40 +0200 Subject: [PATCH 06/15] Remove useless clsx calls. (#61969) * Remove useless clsx calls. * Review fixes. Co-authored-by: DaniGuardiola Co-authored-by: fullofcaffeine Co-authored-by: talldan Co-authored-by: tyxla --- packages/block-library/src/site-logo/edit.js | 3 +-- packages/components/src/animate/index.tsx | 2 +- .../components/src/focal-point-picker/focal-point.tsx | 11 +++++++---- packages/edit-site/src/components/save-panel/index.js | 4 +--- storybook/decorators/with-global-css.js | 10 +++++----- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/packages/block-library/src/site-logo/edit.js b/packages/block-library/src/site-logo/edit.js index 3192f2b000346e..046b5feeb20c99 100644 --- a/packages/block-library/src/site-logo/edit.js +++ b/packages/block-library/src/site-logo/edit.js @@ -73,7 +73,6 @@ const SiteLogo = ( { const [ { naturalWidth, naturalHeight }, setNaturalSize ] = useState( {} ); const [ isEditingImage, setIsEditingImage ] = useState( false ); const { toggleSelection } = useDispatch( blockEditorStore ); - const classes = clsx( 'custom-logo-link' ); const { imageEditing, maxWidth, title } = useSelect( ( select ) => { const settings = select( blockEditorStore ).getSettings(); const siteEntities = select( coreStore ).getEntityRecord( @@ -136,7 +135,7 @@ const SiteLogo = ( { /* eslint-disable jsx-a11y/no-noninteractive-element-interactions, jsx-a11y/click-events-have-key-events */ event.preventDefault() } diff --git a/packages/components/src/animate/index.tsx b/packages/components/src/animate/index.tsx index e7aaf72d243801..e819020447bc9e 100644 --- a/packages/components/src/animate/index.tsx +++ b/packages/components/src/animate/index.tsx @@ -23,7 +23,7 @@ function getDefaultOrigin( type?: GetAnimateOptions[ 'type' ] ) { */ export function getAnimateClassName( options: GetAnimateOptions ) { if ( options.type === 'loading' ) { - return clsx( 'components-animate__loading' ); + return 'components-animate__loading'; } const { type, origin = getDefaultOrigin( type ) } = options; diff --git a/packages/components/src/focal-point-picker/focal-point.tsx b/packages/components/src/focal-point-picker/focal-point.tsx index 7a401eb4c6870b..a03e41d4809cce 100644 --- a/packages/components/src/focal-point-picker/focal-point.tsx +++ b/packages/components/src/focal-point-picker/focal-point.tsx @@ -6,7 +6,6 @@ import { PointerCircle } from './styles/focal-point-style'; /** * External dependencies */ -import clsx from 'clsx'; import type { FocalPointProps } from './types'; import type { WordPressComponentProps } from '../context'; @@ -15,9 +14,13 @@ export default function FocalPoint( { top = '50%', ...props }: WordPressComponentProps< FocalPointProps, 'div' > ) { - const classes = clsx( 'components-focal-point-picker__icon_container' ); - const style = { left, top }; - return ; + return ( + + ); } diff --git a/packages/edit-site/src/components/save-panel/index.js b/packages/edit-site/src/components/save-panel/index.js index 87621638b233fe..1f784edc52234f 100644 --- a/packages/edit-site/src/components/save-panel/index.js +++ b/packages/edit-site/src/components/save-panel/index.js @@ -151,9 +151,7 @@ export default function SavePanel() { > + + + + ); + }, +}; + const trashPostAction = { id: 'move-to-trash', label: __( 'Move to Trash' ), @@ -55,7 +164,7 @@ const trashPostAction = { supportsBulk: true, hideModalHeader: true, RenderModal: ( { - items: posts, + items, closeModal, onActionStart, onActionPerformed, @@ -67,20 +176,22 @@ const trashPostAction = { return ( - { posts.length === 1 + { items.length === 1 ? sprintf( - // translators: %s: The page's title. - __( 'Are you sure you want to delete "%s"?' ), - getItemTitle( posts[ 0 ] ) + // translators: %s: The item's title. + __( + 'Are you sure you want to move to trash "%s"?' + ), + getItemTitle( items[ 0 ] ) ) : sprintf( - // translators: %d: The number of pages (2 or more). + // translators: %d: The number of items (2 or more). _n( - 'Are you sure you want to delete %d page?', - 'Are you sure you want to delete %d pages?', - posts.length + 'Are you sure you want to move to trash %d item?', + 'Are you sure you want to move to trash %d items?', + items.length ), - posts.length + items.length ) } @@ -97,18 +208,18 @@ const trashPostAction = { onClick={ async () => { setIsBusy( true ); if ( onActionStart ) { - onActionStart( posts ); + onActionStart( items ); } const promiseResult = await Promise.allSettled( - posts.map( ( post ) => { - return deleteEntityRecord( + items.map( ( item ) => + deleteEntityRecord( 'postType', - post.type, - post.id, + item.type, + item.id, {}, { throwOnError: true } - ); - } ) + ) + ) ); // If all the promises were fulfilled with success. if ( @@ -119,41 +230,41 @@ const trashPostAction = { let successMessage; if ( promiseResult.length === 1 ) { successMessage = sprintf( - /* translators: The posts's title. */ - __( '"%s" moved to the Trash.' ), - getItemTitle( posts[ 0 ] ) + /* translators: The item's title. */ + __( '"%s" moved to trash.' ), + getItemTitle( items[ 0 ] ) ); - } else if ( posts[ 0 ].type === 'page' ) { + } else if ( items[ 0 ].type === 'page' ) { successMessage = sprintf( - /* translators: The number of pages. */ - __( '%s pages moved to the Trash.' ), - posts.length + /* translators: The number of items. */ + __( '%s items moved to trash.' ), + items.length ); } else { successMessage = sprintf( /* translators: The number of posts. */ - __( '%s posts moved to the Trash.' ), - posts.length + __( '%s items move to trash.' ), + items.length ); } createSuccessNotice( successMessage, { type: 'snackbar', - id: 'trash-post-action', + id: 'move-to-trash-action', } ); } else { - // If there was at lease one failure. + // If there was at least one failure. let errorMessage; - // If we were trying to move a single post to the trash. + // If we were trying to delete a single item. if ( promiseResult.length === 1 ) { if ( promiseResult[ 0 ].reason?.message ) { errorMessage = promiseResult[ 0 ].reason.message; } else { errorMessage = __( - 'An error occurred while moving the post to the trash.' + 'An error occurred while moving to trash the item.' ); } - // If we were trying to move multiple posts to the trash + // If we were trying to delete multiple items. } else { const errorMessages = new Set(); const failedPromises = promiseResult.filter( @@ -168,13 +279,13 @@ const trashPostAction = { } if ( errorMessages.size === 0 ) { errorMessage = __( - 'An error occurred while moving the posts to the trash.' + 'An error occurred while moving to trash the items.' ); } else if ( errorMessages.size === 1 ) { errorMessage = sprintf( /* translators: %s: an error message */ __( - 'An error occurred while moving the posts to the trash: %s' + 'An error occurred while moving to trash the item: %s' ), [ ...errorMessages ][ 0 ] ); @@ -182,7 +293,7 @@ const trashPostAction = { errorMessage = sprintf( /* translators: %s: a list of comma separated error messages */ __( - 'Some errors occurred while moving the pages to the trash: %s' + 'Some errors occurred while moving to trash the items: %s' ), [ ...errorMessages ].join( ',' ) ); @@ -193,7 +304,7 @@ const trashPostAction = { } ); } if ( onActionPerformed ) { - onActionPerformed( posts ); + onActionPerformed( items ); } setIsBusy( false ); closeModal(); @@ -202,7 +313,7 @@ const trashPostAction = { disabled={ isBusy } __experimentalIsFocusable > - { __( 'Delete' ) } + { __( 'Trash' ) } @@ -511,7 +622,7 @@ const renamePostAction = { ) { return true; } - // In the case of templates, we can only remove custom templates. + // In the case of templates, we can only rename custom templates. if ( post.type === TEMPLATE_POST_TYPE ) { return isTemplateRemovable( post ) && post.is_custom; } @@ -850,245 +961,6 @@ const resetTemplateAction = { }, }; -/** - * Check if a template is removable. - * Copy from packages/edit-site/src/utils/is-template-removable.js. - * - * @param {Object} template The template entity to check. - * @return {boolean} Whether the template is revertable. - */ -function isTemplateRemovable( template ) { - if ( ! template ) { - return false; - } - - return ( - template.source === TEMPLATE_ORIGINS.custom && ! template.has_theme_file - ); -} - -const deleteTemplateAction = { - id: 'delete-template', - label: __( 'Delete' ), - isEligible: isTemplateRemovable, - icon: trash, - supportsBulk: true, - hideModalHeader: true, - RenderModal: ( { - items: templates, - closeModal, - onActionStart, - onActionPerformed, - } ) => { - const [ isBusy, setIsBusy ] = useState( false ); - const { removeTemplates } = unlock( useDispatch( editorStore ) ); - return ( - - - { templates.length > 1 - ? sprintf( - // translators: %d: number of items to delete. - _n( - 'Delete %d item?', - 'Delete %d items?', - templates.length - ), - templates.length - ) - : sprintf( - // translators: %s: The template or template part's titles - __( 'Delete "%s"?' ), - decodeEntities( - templates?.[ 0 ]?.title?.rendered - ) - ) } - - - - - - - ); - }, -}; - -const canDeleteOrReset = ( item ) => { - const isTemplatePart = item.type === TEMPLATE_PART_POST_TYPE; - const isUserPattern = item.type === PATTERN_TYPES.user; - return isUserPattern || ( isTemplatePart && item.isCustom ); -}; - -export const deletePatternAction = { - id: 'delete-pattern', - label: __( 'Delete' ), - isEligible: ( item ) => { - if ( ! item ) { - return false; - } - const isTemplatePart = item.type === TEMPLATE_PART_POST_TYPE; - const hasThemeFile = - isTemplatePart && item.templatePart?.has_theme_file; - return canDeleteOrReset( item ) && ! hasThemeFile; - }, - hideModalHeader: true, - supportsBulk: true, - RenderModal: ( { items, closeModal, onActionPerformed } ) => { - const { __experimentalDeleteReusableBlock } = - useDispatch( reusableBlocksStore ); - const { createErrorNotice, createSuccessNotice } = - useDispatch( noticesStore ); - const { removeTemplates } = unlock( useDispatch( editorStore ) ); - - const deletePattern = async () => { - const promiseResult = await Promise.allSettled( - items.map( ( item ) => { - return __experimentalDeleteReusableBlock( item.id ); - } ) - ); - // If all the promises were fulfilled with success. - if ( - promiseResult.every( ( { status } ) => status === 'fulfilled' ) - ) { - let successMessage; - if ( promiseResult.length === 1 ) { - successMessage = sprintf( - /* translators: The posts's title. */ - __( '"%s" deleted.' ), - items[ 0 ].title - ); - } else { - successMessage = __( 'The patterns were deleted.' ); - } - createSuccessNotice( successMessage, { - type: 'snackbar', - id: 'edit-site-page-trashed', - } ); - } else { - // If there was at lease one failure. - let errorMessage; - // If we were trying to delete a single pattern. - if ( promiseResult.length === 1 ) { - if ( promiseResult[ 0 ].reason?.message ) { - errorMessage = promiseResult[ 0 ].reason.message; - } else { - errorMessage = __( - 'An error occurred while deleting the pattern.' - ); - } - // If we were trying to delete multiple patterns. - } else { - const errorMessages = new Set(); - const failedPromises = promiseResult.filter( - ( { status } ) => status === 'rejected' - ); - for ( const failedPromise of failedPromises ) { - if ( failedPromise.reason?.message ) { - errorMessages.add( failedPromise.reason.message ); - } - } - if ( errorMessages.size === 0 ) { - errorMessage = __( - 'An error occurred while deleting the patterns.' - ); - } else if ( errorMessages.size === 1 ) { - errorMessage = sprintf( - /* translators: %s: an error message */ - __( - 'An error occurred while deleting the patterns: %s' - ), - [ ...errorMessages ][ 0 ] - ); - } else { - errorMessage = sprintf( - /* translators: %s: a list of comma separated error messages */ - __( - 'Some errors occurred while deleting the patterns: %s' - ), - [ ...errorMessages ].join( ',' ) - ); - } - createErrorNotice( errorMessage, { - type: 'snackbar', - } ); - } - } - }; - const deleteItem = () => { - if ( items[ 0 ].type === TEMPLATE_PART_POST_TYPE ) { - removeTemplates( items ); - } else { - deletePattern(); - } - if ( onActionPerformed ) { - onActionPerformed(); - } - closeModal(); - }; - let questionMessage; - if ( items.length === 1 ) { - questionMessage = sprintf( - // translators: %s: The page's title. - __( 'Are you sure you want to delete "%s"?' ), - decodeEntities( items[ 0 ].title || items[ 0 ].name ) - ); - } else if ( - items.length > 1 && - items[ 0 ].type === TEMPLATE_PART_POST_TYPE - ) { - questionMessage = sprintf( - // translators: %d: The number of template parts (2 or more). - __( 'Are you sure you want to delete %d template parts?' ), - items.length - ); - } else { - questionMessage = sprintf( - // translators: %d: The number of patterns (2 or more). - __( 'Are you sure you want to delete %d patterns?' ), - items.length - ); - } - return ( - - { questionMessage } - - - - - - ); - }, -}; - export function usePostActions( postType, onActionPerformed ) { const { postTypeObject } = useSelect( ( select ) => { @@ -1125,11 +997,10 @@ export function usePostActions( postType, onActionPerformed ) { renamePostAction, isPattern && exportPatternAsJSONAction, isTemplateOrTemplatePart ? resetTemplateAction : restorePostAction, - isTemplateOrTemplatePart - ? deleteTemplateAction - : permanentlyDeletePostAction, - isPattern && deletePatternAction, - ! isTemplateOrTemplatePart && trashPostAction, + isTemplateOrTemplatePart || isPattern + ? deletePostAction + : trashPostAction, + ! isTemplateOrTemplatePart && permanentlyDeletePostAction, ].filter( Boolean ); if ( onActionPerformed ) { diff --git a/packages/editor/src/store/private-actions.js b/packages/editor/src/store/private-actions.js index c3fca0798e8b70..9304a2fe2c0579 100644 --- a/packages/editor/src/store/private-actions.js +++ b/packages/editor/src/store/private-actions.js @@ -15,7 +15,6 @@ import { decodeEntities } from '@wordpress/html-entities'; * Internal dependencies */ import isTemplateRevertable from './utils/is-template-revertable'; -import { TEMPLATE_POST_TYPE } from './constants'; /** * Returns an action object used to set which template is currently being used/edited. @@ -363,14 +362,13 @@ export const revertTemplate = }; /** - * Action that removes an array of templates. + * Action that removes an array of templates, template parts or patterns. * - * @param {Array} items An array of template or template part objects to remove. + * @param {Array} items An array of template,template part or pattern objects to remove. */ export const removeTemplates = ( items ) => async ( { registry } ) => { - const isTemplate = items[ 0 ].type === TEMPLATE_POST_TYPE; const promiseResult = await Promise.allSettled( items.map( ( item ) => { return registry @@ -402,16 +400,14 @@ export const removeTemplates = decodeEntities( title ) ); } else { - successMessage = isTemplate - ? __( 'Templates deleted.' ) - : __( 'Template parts deleted.' ); + successMessage = __( 'Items deleted.' ); } registry .dispatch( noticesStore ) .createSuccessNotice( successMessage, { type: 'snackbar', - id: 'site-editor-template-deleted-success', + id: 'editor-template-deleted-success', } ); } else { // If there was at lease one failure. @@ -421,11 +417,9 @@ export const removeTemplates = if ( promiseResult[ 0 ].reason?.message ) { errorMessage = promiseResult[ 0 ].reason.message; } else { - errorMessage = isTemplate - ? __( 'An error occurred while deleting the template.' ) - : __( - 'An error occurred while deleting the template part.' - ); + errorMessage = __( + 'An error occurred while deleting the item.' + ); } // If we were trying to delete a multiple templates } else { @@ -439,45 +433,23 @@ export const removeTemplates = } } if ( errorMessages.size === 0 ) { - errorMessage = isTemplate - ? __( - 'An error occurred while deleting the templates.' - ) - : __( - 'An error occurred while deleting the template parts.' - ); + errorMessage = __( + 'An error occurred while deleting the items.' + ); } else if ( errorMessages.size === 1 ) { - errorMessage = isTemplate - ? sprintf( - /* translators: %s: an error message */ - __( - 'An error occurred while deleting the templates: %s' - ), - [ ...errorMessages ][ 0 ] - ) - : sprintf( - /* translators: %s: an error message */ - __( - 'An error occurred while deleting the template parts: %s' - ), - [ ...errorMessages ][ 0 ] - ); + errorMessage = sprintf( + /* translators: %s: an error message */ + __( 'An error occurred while deleting the items: %s' ), + [ ...errorMessages ][ 0 ] + ); } else { - errorMessage = isTemplate - ? sprintf( - /* translators: %s: a list of comma separated error messages */ - __( - 'Some errors occurred while deleting the templates: %s' - ), - [ ...errorMessages ].join( ',' ) - ) - : sprintf( - /* translators: %s: a list of comma separated error messages */ - __( - 'Some errors occurred while deleting the template parts: %s' - ), - [ ...errorMessages ].join( ',' ) - ); + sprintf( + /* translators: %s: a list of comma separated error messages */ + __( + 'Some errors occurred while deleting the items: %s' + ), + [ ...errorMessages ].join( ',' ) + ); } } registry diff --git a/test/e2e/specs/editor/various/change-detection.spec.js b/test/e2e/specs/editor/various/change-detection.spec.js index a737e4eb94a5fc..4ac262f4c1348d 100644 --- a/test/e2e/specs/editor/various/change-detection.spec.js +++ b/test/e2e/specs/editor/various/change-detection.spec.js @@ -420,7 +420,7 @@ test.describe( 'Change detection', () => { .click(); await page .getByRole( 'dialog' ) - .getByRole( 'button', { name: 'Delete' } ) + .getByRole( 'button', { name: 'Trash' } ) .click(); await expect( page ).toHaveURL( '/wp-admin/edit.php?post_type=post' ); From 07207a914fd59dc07c8a8b14dff56391461af75d Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 27 May 2024 18:48:48 +0200 Subject: [PATCH 09/15] Improve distclean script (#62019) Change `distclean` script to use `git clean`. Ostensibly, `distclean` is a script to reset the repository to a clean state, close to what a fresh clone would look like. Before this change, it only removed `node_modules`. This leaves a lot of built assets that can potentially cause issues. For example, the compressed-size github action uses `distclean` to reset the repo to a clean state when switching branches, which can continue to cause problems (observed in https://github.com/WordPress/gutenberg/pull/62008). This change uses `git clean --force -d -X` to "reset" the repository. From the `git-clean` manpage: Cleans the working tree by recursively removing files that are not under version control, starting from the current directory. -f, --force If the Git configuration variable clean.requireForce is not set to false, git clean will refuse to delete files or directories unless given -f. Git will refuse to modify untracked nested git repositories (directories with a .git subdirectory) unless a second -f is given. -d Normally, when no is specified, git clean will not recurse into untracked directories to avoid removing too much. Specify -d to have it recurse into such directories as well. If a is specified, -d is irrelevant; all untracked files matching the specified paths (with exceptions for nested git directories mentioned under --force) will be removed. -X Remove only files ignored by Git. This may be useful to rebuild everything from scratch, but keep manually created files. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ac50b0caf19479..f218f9ca808205 100644 --- a/package.json +++ b/package.json @@ -276,7 +276,7 @@ "clean:packages": "rimraf \"./packages/*/@(build|build-module|build-style)\"", "dev": "npm run build:packages && concurrently \"wp-scripts start\" \"npm run dev:packages\"", "dev:packages": "concurrently \"node ./bin/packages/watch.js\" \"tsc --build --watch\"", - "distclean": "rimraf node_modules packages/*/node_modules", + "distclean": "git clean --force -d -X", "docs:api-ref": "node ./bin/api-docs/update-api-docs.js", "docs:blocks": "node ./bin/api-docs/gen-block-lib-list.js", "docs:build": "npm-run-all docs:gen docs:blocks docs:api-ref docs:theme-ref", From 2097e842f135c1c596f0f96e72d6bdae461d3cb8 Mon Sep 17 00:00:00 2001 From: Nik Tsekouras Date: Mon, 27 May 2024 20:53:19 +0300 Subject: [PATCH 10/15] Editor: Remove obsolete `listViewLabel` prop from DocumentTools (#62032) Co-authored-by: ntsekouras Co-authored-by: Mamaduka --- packages/editor/src/components/document-tools/index.js | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/packages/editor/src/components/document-tools/index.js b/packages/editor/src/components/document-tools/index.js index 6952fa34e31ae9..6ec999bd048012 100644 --- a/packages/editor/src/components/document-tools/index.js +++ b/packages/editor/src/components/document-tools/index.js @@ -32,12 +32,7 @@ const preventDefault = ( event ) => { event.preventDefault(); }; -function DocumentTools( { - className, - disableBlockTools = false, - // This is a temporary prop until the list view is fully unified between post and site editors. - listViewLabel = __( 'Document Overview' ), -} ) { +function DocumentTools( { className, disableBlockTools = false } ) { const { setIsInserterOpened, setIsListViewOpened } = useDispatch( editorStore ); const { @@ -164,7 +159,7 @@ function DocumentTools( { disabled={ disableBlockTools } isPressed={ isListViewOpen } /* translators: button label text should, if possible, be under 16 characters. */ - label={ listViewLabel } + label={ __( 'Document Overview' ) } onClick={ toggleListView } shortcut={ listViewShortcut } showTooltip={ ! showIconLabels } From b3cfec402fefe61830d4ccbd33cc5937a8c452f4 Mon Sep 17 00:00:00 2001 From: Ramon Date: Tue, 28 May 2024 10:04:46 +1000 Subject: [PATCH 11/15] Background image: update controls defaults and layout (#62000) * Background image: add functionality to remove a theme's default, site-wide background image in the editor by settings the value to `background-image: none` * Background image: harmonize headings, update copy including changing the label "Fixed" to "Tile", using horizontal layout for image size and repeat, fixing bug where width input is cleared and the size defaults to "cover" * Make sure the visually hidden labels are correct - use either the image title or image filename. Where there is no image URL, then show no background image selected Co-authored-by: ramonjd Co-authored-by: jasmussen Co-authored-by: andrewserong --- .../global-styles/background-panel.js | 65 ++++++++++++------- .../global-styles/background-panel.js | 2 - 2 files changed, 40 insertions(+), 27 deletions(-) diff --git a/packages/block-editor/src/components/global-styles/background-panel.js b/packages/block-editor/src/components/global-styles/background-panel.js index 2e73f52564362e..b7cf7f2bbc493d 100644 --- a/packages/block-editor/src/components/global-styles/background-panel.js +++ b/packages/block-editor/src/components/global-styles/background-panel.js @@ -102,7 +102,7 @@ function backgroundSizeHelpText( value ) { if ( value === 'contain' ) { return __( 'Image is contained without distortion.' ); } - return __( 'Specify a fixed width.' ); + return __( 'Image has a fixed width.' ); } /** @@ -174,13 +174,13 @@ function InspectorImagePreview( { label, filename, url: imgUrl } ) { { imgLabel } - { filename + { imgUrl ? sprintf( /* translators: %s: file name */ - __( 'Selected image: %s' ), - filename + __( 'Background image: %s' ), + filename || imgLabel ) - : __( 'No image selected' ) } + : __( 'No background image selected' ) } @@ -321,7 +321,7 @@ function BackgroundImageToolsPanelItem( { name={ - { currentValueForToggle !== undefined && - currentValueForToggle !== 'cover' && - currentValueForToggle !== 'contain' ? ( - - ) : null } - { currentValueForToggle !== 'cover' && ( - - ) } + + { currentValueForToggle !== undefined && + currentValueForToggle !== 'cover' && + currentValueForToggle !== 'contain' ? ( + + ) : null } + { currentValueForToggle !== 'cover' && ( + + ) } + ); } diff --git a/packages/edit-site/src/components/global-styles/background-panel.js b/packages/edit-site/src/components/global-styles/background-panel.js index 0ad74e0cd0bdd5..8a372587bc66e5 100644 --- a/packages/edit-site/src/components/global-styles/background-panel.js +++ b/packages/edit-site/src/components/global-styles/background-panel.js @@ -2,7 +2,6 @@ * WordPress dependencies */ import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor'; -import { __ } from '@wordpress/i18n'; /** * Internal dependencies @@ -59,7 +58,6 @@ export default function BackgroundPanel() { value={ style } onChange={ setStyle } settings={ settings } - headerLabel={ __( 'Background' ) } defaultValues={ BACKGROUND_DEFAULT_VALUES } defaultControls={ defaultControls } themeFileURIs={ _links?.[ 'wp:theme-file' ] } From 65ca1d4080efc3975413eb5b6eada3753ad3040f Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Tue, 28 May 2024 09:52:23 +0800 Subject: [PATCH 12/15] Remove client-side IS_GUTENBERG_PLUGIN check that prevents registration of pattern overrides source (#62011) Co-authored-by: talldan Co-authored-by: SantosGuillamot --- packages/editor/src/bindings/index.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/editor/src/bindings/index.js b/packages/editor/src/bindings/index.js index 5824cdde022cc6..182edc621453ed 100644 --- a/packages/editor/src/bindings/index.js +++ b/packages/editor/src/bindings/index.js @@ -12,7 +12,4 @@ import postMeta from './post-meta'; const { registerBlockBindingsSource } = unlock( dispatch( blocksStore ) ); registerBlockBindingsSource( postMeta ); - -if ( globalThis.IS_GUTENBERG_PLUGIN ) { - registerBlockBindingsSource( patternOverrides ); -} +registerBlockBindingsSource( patternOverrides ); From bf3c61185eb9dfbc9b99cac44812c59a28b438d4 Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Tue, 28 May 2024 07:20:29 +0200 Subject: [PATCH 13/15] Styles: Level specificity using :root to fix reset styles (#61638) Co-authored-by: ellatrix Co-authored-by: aaronrobertshaw Co-authored-by: tellthemachines Co-authored-by: talldan Co-authored-by: andrewserong Co-authored-by: kevin940726 --- backport-changelog/6.6/6522.md | 5 + lib/class-wp-theme-json-gutenberg.php | 14 ++- lib/theme.json | 34 ++++++ .../test/use-global-styles-output.js | 21 ++-- .../global-styles/use-global-styles-output.js | 108 +++++++++--------- packages/block-library/src/audio/theme.scss | 2 +- packages/block-library/src/button/editor.scss | 35 ------ packages/block-library/src/button/style.scss | 72 ++++-------- packages/block-library/src/cover/style.scss | 32 +++--- packages/block-library/src/embed/theme.scss | 2 +- .../block-library/src/gallery/editor.scss | 5 +- packages/block-library/src/image/style.scss | 51 ++------- packages/block-library/src/image/theme.scss | 4 +- .../src/latest-posts/editor.scss | 15 ++- .../block-library/src/latest-posts/style.scss | 15 ++- .../block-library/src/pullquote/editor.scss | 2 + .../block-library/src/pullquote/style.scss | 10 +- .../block-library/src/pullquote/theme.scss | 4 +- packages/block-library/src/quote/theme.scss | 2 +- .../block-library/src/separator/editor.scss | 7 -- .../block-library/src/separator/style.scss | 52 +++++---- .../block-library/src/site-logo/style.scss | 12 +- .../block-library/src/site-title/editor.scss | 6 +- .../block-library/src/site-title/style.scss | 6 +- .../block-library/src/social-link/editor.scss | 4 +- .../src/social-links/editor.scss | 25 ++-- .../block-library/src/social-links/style.scss | 29 ++--- packages/block-library/src/table/style.scss | 3 + packages/block-library/src/table/theme.scss | 6 +- .../block-library/src/tag-cloud/style.scss | 28 ++--- .../src/template-part/theme.scss | 12 +- packages/block-library/src/video/theme.scss | 2 +- phpunit/class-wp-theme-json-test.php | 84 +++++++------- test/e2e/specs/editor/various/styles.spec.js | 17 +++ test/e2e/specs/site-editor/styles.spec.js | 59 ++++++++++ 35 files changed, 401 insertions(+), 384 deletions(-) create mode 100644 backport-changelog/6.6/6522.md create mode 100644 test/e2e/specs/editor/various/styles.spec.js create mode 100644 test/e2e/specs/site-editor/styles.spec.js diff --git a/backport-changelog/6.6/6522.md b/backport-changelog/6.6/6522.md new file mode 100644 index 00000000000000..172464cf664de9 --- /dev/null +++ b/backport-changelog/6.6/6522.md @@ -0,0 +1,5 @@ +https://github.com/WordPress/wordpress-develop/pull/6522 + +* https://github.com/WordPress/gutenberg/pull/60106 +* https://github.com/WordPress/gutenberg/pull/60228 +* https://github.com/WordPress/gutenberg/pull/61638 diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index 1dec7b164d880b..75b9ef60ff1fc8 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -1293,7 +1293,7 @@ protected function process_blocks_custom_css( $css, $selector ) { $is_root_css = ( ! str_contains( $part, '{' ) ); if ( $is_root_css ) { // If the part doesn't contain braces, it applies to the root level. - $processed_css .= trim( $selector ) . '{' . trim( $part ) . '}'; + $processed_css .= ':root :where(' . trim( $selector ) . '){' . trim( $part ) . '}'; } else { // If the part contains braces, it's a nested CSS rule. $part = explode( '{', str_replace( '}', '', $part ) ); @@ -1305,7 +1305,8 @@ protected function process_blocks_custom_css( $css, $selector ) { $part_selector = str_starts_with( $nested_selector, ' ' ) ? static::scope_selector( $selector, $nested_selector ) : static::append_to_selector( $selector, $nested_selector ); - $processed_css .= $part_selector . '{' . trim( $css_value ) . '}'; + $final_selector = ":root :where($part_selector)"; + $processed_css .= $final_selector . '{' . trim( $css_value ) . '}'; } } return $processed_css; @@ -1322,6 +1323,7 @@ public function get_custom_css() { $block_custom_css = ''; $block_nodes = $this->get_block_custom_css_nodes(); foreach ( $block_nodes as $node ) { + // The node selector will have its specificity set to 0-1-0 within process_blocks_custom_css. $block_custom_css .= $this->get_block_custom_css( $node['css'], $node['selector'] ); } @@ -1564,7 +1566,7 @@ protected function get_layout_styles( $block_metadata, $types = array() ) { $spacing_rule['selector'] ); } else { - $format = static::ROOT_BLOCK_SELECTOR === $selector ? ':where(.%2$s) %3$s' : ':where(%1$s-%2$s) %3$s'; + $format = static::ROOT_BLOCK_SELECTOR === $selector ? '.%2$s %3$s' : '%1$s-%2$s %3$s'; $layout_selector = sprintf( $format, $selector, @@ -2745,7 +2747,7 @@ static function ( $pseudo_selector ) use ( $selector ) { } // 2. Generate and append the rules that use the general selector. - $block_rules .= static::to_ruleset( ":where($selector)", $declarations ); + $block_rules .= static::to_ruleset( ":root :where($selector)", $declarations ); // 3. Generate and append the rules that use the duotone selector. if ( isset( $block_metadata['duotone'] ) && ! empty( $declarations_duotone ) ) { @@ -2762,12 +2764,12 @@ static function ( $pseudo_selector ) use ( $selector ) { // 5. Generate and append the feature level rulesets. foreach ( $feature_declarations as $feature_selector => $individual_feature_declarations ) { - $block_rules .= static::to_ruleset( ":where($feature_selector)", $individual_feature_declarations ); + $block_rules .= static::to_ruleset( ":root :where($feature_selector)", $individual_feature_declarations ); } // 6. Generate and append the style variation rulesets. foreach ( $style_variation_declarations as $style_variation_selector => $individual_style_variation_declarations ) { - $block_rules .= static::to_ruleset( $style_variation_selector, $individual_style_variation_declarations ); + $block_rules .= static::to_ruleset( ":root :where($style_variation_selector)", $individual_style_variation_declarations ); } return $block_rules; diff --git a/lib/theme.json b/lib/theme.json index 7cd6129923df2a..2f1f723bf75f7f 100644 --- a/lib/theme.json +++ b/lib/theme.json @@ -370,6 +370,40 @@ "bottom": "0px", "left": "0px" } + }, + "blocks": { + "core/button": { + "variations": { + "outline": { + "border": { + "width": "2px", + "style": "solid", + "color": "currentColor" + }, + "color": { + "text": "currentColor", + "gradient": "transparent none" + }, + "spacing": { + "padding": { + "top": "0.667em", + "right": "1.33em", + "bottom": "0.667em", + "left": "1.33em" + } + } + } + } + }, + "core/site-logo": { + "variations": { + "rounded": { + "border": { + "radius": "9999px" + } + } + } + } } } } diff --git a/packages/block-editor/src/components/global-styles/test/use-global-styles-output.js b/packages/block-editor/src/components/global-styles/test/use-global-styles-output.js index 95de3d4007079c..b858a2e4140ea9 100644 --- a/packages/block-editor/src/components/global-styles/test/use-global-styles-output.js +++ b/packages/block-editor/src/components/global-styles/test/use-global-styles-output.js @@ -480,7 +480,7 @@ describe( 'global styles renderer', () => { }; expect( toStyles( tree, blockSelectors ) ).toEqual( - ':where(body) {margin: 0;}.is-layout-flow > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.is-layout-flow > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.is-layout-flow > .aligncenter { margin-left: auto !important; margin-right: auto !important; }.is-layout-constrained > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.is-layout-constrained > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.is-layout-constrained > .aligncenter { margin-left: auto !important; margin-right: auto !important; }.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)) { max-width: var(--wp--style--global--content-size); margin-left: auto !important; margin-right: auto !important; }.is-layout-constrained > .alignwide { max-width: var(--wp--style--global--wide-size); }body .is-layout-flex { display:flex; }.is-layout-flex { flex-wrap: wrap; align-items: center; }.is-layout-flex > :is(*, div) { margin: 0; }body .is-layout-grid { display:grid; }.is-layout-grid > :is(*, div) { margin: 0; }:where(body){background-color: red;margin: 10px;padding: 10px;}:where(a:where(:not(.wp-element-button))){color: blue;}a:where(:not(.wp-element-button)):hover{color: orange;}a:where(:not(.wp-element-button)):focus{color: orange;}:where(h1){font-size: 42px;}:where(.wp-block-group){margin-top: 10px;margin-right: 20px;margin-bottom: 30px;margin-left: 40px;padding-top: 11px;padding-right: 22px;padding-bottom: 33px;padding-left: 44px;}:where(h1,h2,h3,h4,h5,h6){color: orange;}:where(h1 a:where(:not(.wp-element-button)),h2 a:where(:not(.wp-element-button)),h3 a:where(:not(.wp-element-button)),h4 a:where(:not(.wp-element-button)),h5 a:where(:not(.wp-element-button)),h6 a:where(:not(.wp-element-button))){color: hotpink;}h1 a:where(:not(.wp-element-button)):hover,h2 a:where(:not(.wp-element-button)):hover,h3 a:where(:not(.wp-element-button)):hover,h4 a:where(:not(.wp-element-button)):hover,h5 a:where(:not(.wp-element-button)):hover,h6 a:where(:not(.wp-element-button)):hover{color: red;}h1 a:where(:not(.wp-element-button)):focus,h2 a:where(:not(.wp-element-button)):focus,h3 a:where(:not(.wp-element-button)):focus,h4 a:where(:not(.wp-element-button)):focus,h5 a:where(:not(.wp-element-button)):focus,h6 a:where(:not(.wp-element-button)):focus{color: red;}:where(.wp-block-image img, .wp-block-image .wp-crop-area){border-radius: 9999px;}:where(.wp-block-image){color: red;}.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }.has-white-color{color: var(--wp--preset--color--white) !important;}.has-white-background-color{background-color: var(--wp--preset--color--white) !important;}.has-white-border-color{border-color: var(--wp--preset--color--white) !important;}.has-black-color{color: var(--wp--preset--color--black) !important;}.has-black-background-color{background-color: var(--wp--preset--color--black) !important;}.has-black-border-color{border-color: var(--wp--preset--color--black) !important;}h1.has-blue-color,h2.has-blue-color,h3.has-blue-color,h4.has-blue-color,h5.has-blue-color,h6.has-blue-color{color: var(--wp--preset--color--blue) !important;}h1.has-blue-background-color,h2.has-blue-background-color,h3.has-blue-background-color,h4.has-blue-background-color,h5.has-blue-background-color,h6.has-blue-background-color{background-color: var(--wp--preset--color--blue) !important;}h1.has-blue-border-color,h2.has-blue-border-color,h3.has-blue-border-color,h4.has-blue-border-color,h5.has-blue-border-color,h6.has-blue-border-color{border-color: var(--wp--preset--color--blue) !important;}' + ':where(body) {margin: 0;}.is-layout-flow > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.is-layout-flow > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.is-layout-flow > .aligncenter { margin-left: auto !important; margin-right: auto !important; }.is-layout-constrained > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.is-layout-constrained > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.is-layout-constrained > .aligncenter { margin-left: auto !important; margin-right: auto !important; }.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)) { max-width: var(--wp--style--global--content-size); margin-left: auto !important; margin-right: auto !important; }.is-layout-constrained > .alignwide { max-width: var(--wp--style--global--wide-size); }body .is-layout-flex { display:flex; }.is-layout-flex { flex-wrap: wrap; align-items: center; }.is-layout-flex > :is(*, div) { margin: 0; }body .is-layout-grid { display:grid; }.is-layout-grid > :is(*, div) { margin: 0; }:root :where(body){background-color: red;margin: 10px;padding: 10px;}:root :where(a:where(:not(.wp-element-button))){color: blue;}a:where(:not(.wp-element-button)):hover{color: orange;}a:where(:not(.wp-element-button)):focus{color: orange;}:root :where(h1){font-size: 42px;}:root :where(.wp-block-group){margin-top: 10px;margin-right: 20px;margin-bottom: 30px;margin-left: 40px;padding-top: 11px;padding-right: 22px;padding-bottom: 33px;padding-left: 44px;}:root :where(h1,h2,h3,h4,h5,h6){color: orange;}:root :where(h1 a:where(:not(.wp-element-button)),h2 a:where(:not(.wp-element-button)),h3 a:where(:not(.wp-element-button)),h4 a:where(:not(.wp-element-button)),h5 a:where(:not(.wp-element-button)),h6 a:where(:not(.wp-element-button))){color: hotpink;}h1 a:where(:not(.wp-element-button)):hover,h2 a:where(:not(.wp-element-button)):hover,h3 a:where(:not(.wp-element-button)):hover,h4 a:where(:not(.wp-element-button)):hover,h5 a:where(:not(.wp-element-button)):hover,h6 a:where(:not(.wp-element-button)):hover{color: red;}h1 a:where(:not(.wp-element-button)):focus,h2 a:where(:not(.wp-element-button)):focus,h3 a:where(:not(.wp-element-button)):focus,h4 a:where(:not(.wp-element-button)):focus,h5 a:where(:not(.wp-element-button)):focus,h6 a:where(:not(.wp-element-button)):focus{color: red;}:root :where(.wp-block-image img, .wp-block-image .wp-crop-area){border-radius: 9999px;}:root :where(.wp-block-image){color: red;}.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }.has-white-color{color: var(--wp--preset--color--white) !important;}.has-white-background-color{background-color: var(--wp--preset--color--white) !important;}.has-white-border-color{border-color: var(--wp--preset--color--white) !important;}.has-black-color{color: var(--wp--preset--color--black) !important;}.has-black-background-color{background-color: var(--wp--preset--color--black) !important;}.has-black-border-color{border-color: var(--wp--preset--color--black) !important;}h1.has-blue-color,h2.has-blue-color,h3.has-blue-color,h4.has-blue-color,h5.has-blue-color,h6.has-blue-color{color: var(--wp--preset--color--blue) !important;}h1.has-blue-background-color,h2.has-blue-background-color,h3.has-blue-background-color,h4.has-blue-background-color,h5.has-blue-background-color,h6.has-blue-background-color{background-color: var(--wp--preset--color--blue) !important;}h1.has-blue-border-color,h2.has-blue-border-color,h3.has-blue-border-color,h4.has-blue-border-color,h5.has-blue-border-color,h6.has-blue-border-color{border-color: var(--wp--preset--color--blue) !important;}' ); } ); @@ -520,7 +520,7 @@ describe( 'global styles renderer', () => { }; expect( toStyles( Object.freeze( tree ), blockSelectors ) ).toEqual( - ':where(body) {margin: 0;}.is-layout-flow > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.is-layout-flow > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.is-layout-flow > .aligncenter { margin-left: auto !important; margin-right: auto !important; }.is-layout-constrained > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.is-layout-constrained > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.is-layout-constrained > .aligncenter { margin-left: auto !important; margin-right: auto !important; }.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)) { max-width: var(--wp--style--global--content-size); margin-left: auto !important; margin-right: auto !important; }.is-layout-constrained > .alignwide { max-width: var(--wp--style--global--wide-size); }body .is-layout-flex { display:flex; }.is-layout-flex { flex-wrap: wrap; align-items: center; }.is-layout-flex > :is(*, div) { margin: 0; }body .is-layout-grid { display:grid; }.is-layout-grid > :is(*, div) { margin: 0; }:where(.wp-image-spacing){padding-top: 1px;}:where(.wp-image-border-color){border-color: red;}:where(.wp-image-border){border-radius: 9999px;}:where(.wp-image){color: red;}.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }' + ':where(body) {margin: 0;}.is-layout-flow > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.is-layout-flow > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.is-layout-flow > .aligncenter { margin-left: auto !important; margin-right: auto !important; }.is-layout-constrained > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.is-layout-constrained > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.is-layout-constrained > .aligncenter { margin-left: auto !important; margin-right: auto !important; }.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)) { max-width: var(--wp--style--global--content-size); margin-left: auto !important; margin-right: auto !important; }.is-layout-constrained > .alignwide { max-width: var(--wp--style--global--wide-size); }body .is-layout-flex { display:flex; }.is-layout-flex { flex-wrap: wrap; align-items: center; }.is-layout-flex > :is(*, div) { margin: 0; }body .is-layout-grid { display:grid; }.is-layout-grid > :is(*, div) { margin: 0; }:root :where(.wp-image-spacing){padding-top: 1px;}:root :where(.wp-image-border-color){border-color: red;}:root :where(.wp-image-border){border-radius: 9999px;}:root :where(.wp-image){color: red;}.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }' ); } ); @@ -566,7 +566,8 @@ describe( 'global styles renderer', () => { }; expect( toStyles( Object.freeze( tree ), blockSelectors ) ).toEqual( - ':where(body) {margin: 0;}.is-layout-flow > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.is-layout-flow > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.is-layout-flow > .aligncenter { margin-left: auto !important; margin-right: auto !important; }.is-layout-constrained > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.is-layout-constrained > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.is-layout-constrained > .aligncenter { margin-left: auto !important; margin-right: auto !important; }.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)) { max-width: var(--wp--style--global--content-size); margin-left: auto !important; margin-right: auto !important; }.is-layout-constrained > .alignwide { max-width: var(--wp--style--global--wide-size); }body .is-layout-flex { display:flex; }.is-layout-flex { flex-wrap: wrap; align-items: center; }.is-layout-flex > :is(*, div) { margin: 0; }body .is-layout-grid { display:grid; }.is-layout-grid > :is(*, div) { margin: 0; }.is-style-foo.wp-image.wp-image-spacing{padding-top: 2px;}.is-style-foo.wp-image.wp-image-border-color{border-color: blue;}.is-style-foo.wp-image{color: blue;}.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }' + ':where(body) {margin: 0;}.is-layout-flow > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.is-layout-flow > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.is-layout-flow > .aligncenter { margin-left: auto !important; margin-right: auto !important; }.is-layout-constrained > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.is-layout-constrained > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.is-layout-constrained > .aligncenter { margin-left: auto !important; margin-right: auto !important; }.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)) { max-width: var(--wp--style--global--content-size); margin-left: auto !important; margin-right: auto !important; }.is-layout-constrained > .alignwide { max-width: var(--wp--style--global--wide-size); }body .is-layout-flex { display:flex; }.is-layout-flex { flex-wrap: wrap; align-items: center; }.is-layout-flex > :is(*, div) { margin: 0; }body .is-layout-grid { display:grid; }.is-layout-grid > :is(*, div) { margin: 0; }' + + ':root :where(.is-style-foo.wp-image.wp-image-spacing){padding-top: 2px;}:root :where(.is-style-foo.wp-image.wp-image-border-color){border-color: blue;}:root :where(.is-style-foo.wp-image){color: blue;}.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }' ); } ); @@ -725,7 +726,7 @@ describe( 'global styles renderer', () => { } ); expect( layoutStyles ).toEqual( - ':where(.is-layout-flow) > * { margin-block-start: 0; margin-block-end: 0; }:where(.is-layout-flow) > * + * { margin-block-start: 0.5em; margin-block-end: 0; }:where(.is-layout-flex) { gap: 0.5em; }:root { --wp--style--block-gap: 0.5em; }.is-layout-flow > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.is-layout-flow > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.is-layout-flow > .aligncenter { margin-left: auto !important; margin-right: auto !important; }body .is-layout-flex { display:flex; }.is-layout-flex { flex-wrap: wrap; align-items: center; }.is-layout-flex > * { margin: 0; }' + '.is-layout-flow > * { margin-block-start: 0; margin-block-end: 0; }.is-layout-flow > * + * { margin-block-start: 0.5em; margin-block-end: 0; }.is-layout-flex { gap: 0.5em; }:root { --wp--style--block-gap: 0.5em; }.is-layout-flow > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.is-layout-flow > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.is-layout-flow > .aligncenter { margin-left: auto !important; margin-right: auto !important; }body .is-layout-flex { display:flex; }.is-layout-flex { flex-wrap: wrap; align-items: center; }.is-layout-flex > * { margin: 0; }' ); } ); @@ -742,7 +743,7 @@ describe( 'global styles renderer', () => { } ); expect( layoutStyles ).toEqual( - ':where(.is-layout-flow) > * { margin-block-start: 0; margin-block-end: 0; }:where(.is-layout-flow) > * + * { margin-block-start: 12px; margin-block-end: 0; }:where(.is-layout-flex) { gap: 12px; }:root { --wp--style--block-gap: 12px; }.is-layout-flow > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.is-layout-flow > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.is-layout-flow > .aligncenter { margin-left: auto !important; margin-right: auto !important; }body .is-layout-flex { display:flex; }.is-layout-flex { flex-wrap: wrap; align-items: center; }.is-layout-flex > * { margin: 0; }' + '.is-layout-flow > * { margin-block-start: 0; margin-block-end: 0; }.is-layout-flow > * + * { margin-block-start: 12px; margin-block-end: 0; }.is-layout-flex { gap: 12px; }:root { --wp--style--block-gap: 12px; }.is-layout-flow > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.is-layout-flow > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.is-layout-flow > .aligncenter { margin-left: auto !important; margin-right: auto !important; }body .is-layout-flex { display:flex; }.is-layout-flex { flex-wrap: wrap; align-items: center; }.is-layout-flex > * { margin: 0; }' ); } ); @@ -759,7 +760,7 @@ describe( 'global styles renderer', () => { } ); expect( layoutStyles ).toEqual( - ':where(.wp-block-group-is-layout-flow) > * { margin-block-start: 0; margin-block-end: 0; }:where(.wp-block-group-is-layout-flow) > * + * { margin-block-start: 12px; margin-block-end: 0; }:where(.wp-block-group-is-layout-flex) { gap: 12px; }' + '.wp-block-group-is-layout-flow > * { margin-block-start: 0; margin-block-end: 0; }.wp-block-group-is-layout-flow > * + * { margin-block-start: 12px; margin-block-end: 0; }.wp-block-group-is-layout-flex { gap: 12px; }' ); } ); @@ -996,7 +997,7 @@ describe( 'global styles renderer', () => { it( 'should return processed CSS without any nested selectors', () => { expect( processCSSNesting( 'color: red; margin: auto;', '.foo' ) - ).toEqual( '.foo{color: red; margin: auto;}' ); + ).toEqual( ':root :where(.foo){color: red; margin: auto;}' ); } ); it( 'should return processed CSS with nested selectors', () => { expect( @@ -1005,7 +1006,7 @@ describe( 'global styles renderer', () => { '.foo' ) ).toEqual( - '.foo{color: red; margin: auto;}.foo.one{color: blue;}.foo .two{color: green;}' + ':root :where(.foo){color: red; margin: auto;}:root :where(.foo.one){color: blue;}:root :where(.foo .two){color: green;}' ); } ); it( 'should return processed CSS with pseudo elements', () => { @@ -1015,7 +1016,7 @@ describe( 'global styles renderer', () => { '.foo' ) ).toEqual( - '.foo{color: red; margin: auto;}.foo::before{color: blue;}.foo ::before{color: green;}.foo.one::before{color: yellow;}.foo .two::before{color: purple;}' + ':root :where(.foo){color: red; margin: auto;}:root :where(.foo::before){color: blue;}:root :where(.foo ::before){color: green;}:root :where(.foo.one::before){color: yellow;}:root :where(.foo .two::before){color: purple;}' ); } ); it( 'should return processed CSS with multiple root selectors', () => { @@ -1025,7 +1026,7 @@ describe( 'global styles renderer', () => { '.foo, .bar' ) ).toEqual( - '.foo, .bar{color: red; margin: auto;}.foo.one, .bar.one{color: blue;}.foo .two, .bar .two{color: green;}.foo::before, .bar::before{color: yellow;}.foo ::before, .bar ::before{color: purple;}.foo.three::before, .bar.three::before{color: orange;}.foo .four::before, .bar .four::before{color: skyblue;}' + ':root :where(.foo, .bar){color: red; margin: auto;}:root :where(.foo.one, .bar.one){color: blue;}:root :where(.foo .two, .bar .two){color: green;}:root :where(.foo::before, .bar::before){color: yellow;}:root :where(.foo ::before, .bar ::before){color: purple;}:root :where(.foo.three::before, .bar.three::before){color: orange;}:root :where(.foo .four::before, .bar .four::before){color: skyblue;}' ); } ); } ); diff --git a/packages/block-editor/src/components/global-styles/use-global-styles-output.js b/packages/block-editor/src/components/global-styles/use-global-styles-output.js index 981189309f828b..06d9400416eebb 100644 --- a/packages/block-editor/src/components/global-styles/use-global-styles-output.js +++ b/packages/block-editor/src/components/global-styles/use-global-styles-output.js @@ -522,10 +522,10 @@ export function getLayoutStyles( { } else { combinedSelector = selector === ROOT_BLOCK_SELECTOR - ? `:where(.${ className })${ + ? `.${ className }${ spacingStyle?.selector || '' }` - : `:where(${ selector }-${ className })${ + : `${ selector }-${ className }${ spacingStyle?.selector || '' }`; } @@ -860,12 +860,56 @@ export const toStyles = ( ( [ cssSelector, declarations ] ) => { if ( declarations.length ) { const rules = declarations.join( ';' ); - ruleset += `:where(${ cssSelector }){${ rules };}`; + ruleset += `:root :where(${ cssSelector }){${ rules };}`; } } ); } + // Process duotone styles. + if ( duotoneSelector ) { + const duotoneStyles = {}; + if ( styles?.filter ) { + duotoneStyles.filter = styles.filter; + delete styles.filter; + } + const duotoneDeclarations = + getStylesDeclarations( duotoneStyles ); + if ( duotoneDeclarations.length ) { + ruleset += `${ duotoneSelector }{${ duotoneDeclarations.join( + ';' + ) };}`; + } + } + + // Process blockGap and layout styles. + if ( + ! disableLayoutStyles && + ( ROOT_BLOCK_SELECTOR === selector || hasLayoutSupport ) + ) { + ruleset += getLayoutStyles( { + style: styles, + selector, + hasBlockGapSupport, + hasFallbackGapSupport, + fallbackGapValue, + } ); + } + + // Process the remaining block styles (they use either normal block class or __experimentalSelector). + const styleDeclarations = getStylesDeclarations( + styles, + selector, + useRootPaddingAlign, + tree, + disableRootPadding + ); + if ( styleDeclarations?.length ) { + ruleset += `:root :where(${ selector }){${ styleDeclarations.join( + ';' + ) };}`; + } + if ( styleVariationSelectors ) { Object.entries( styleVariationSelectors ).forEach( ( [ styleVariationName, styleVariationSelector ] ) => { @@ -892,7 +936,7 @@ export const toStyles = ( ); const rules = declarations.join( ';' ); - ruleset += `${ cssSelector }{${ rules };}`; + ruleset += `:root :where(${ cssSelector }){${ rules };}`; } } ); @@ -907,7 +951,7 @@ export const toStyles = ( tree ); if ( styleVariationDeclarations.length ) { - ruleset += `${ styleVariationSelector }{${ styleVariationDeclarations.join( + ruleset += `:root :where(${ styleVariationSelector }){${ styleVariationDeclarations.join( ';' ) };}`; } @@ -916,50 +960,6 @@ export const toStyles = ( ); } - // Process duotone styles. - if ( duotoneSelector ) { - const duotoneStyles = {}; - if ( styles?.filter ) { - duotoneStyles.filter = styles.filter; - delete styles.filter; - } - const duotoneDeclarations = - getStylesDeclarations( duotoneStyles ); - if ( duotoneDeclarations.length ) { - ruleset += `${ duotoneSelector }{${ duotoneDeclarations.join( - ';' - ) };}`; - } - } - - // Process blockGap and layout styles. - if ( - ! disableLayoutStyles && - ( ROOT_BLOCK_SELECTOR === selector || hasLayoutSupport ) - ) { - ruleset += getLayoutStyles( { - style: styles, - selector, - hasBlockGapSupport, - hasFallbackGapSupport, - fallbackGapValue, - } ); - } - - // Process the remaining block styles (they use either normal block class or __experimentalSelector). - const declarations = getStylesDeclarations( - styles, - selector, - useRootPaddingAlign, - tree, - disableRootPadding - ); - if ( declarations?.length ) { - ruleset += `:where(${ selector }){${ declarations.join( - ';' - ) };}`; - } - // Check for pseudo selector in `styles` and handle separately. const pseudoSelectorStyles = Object.entries( styles ).filter( ( [ key ] ) => key.startsWith( ':' ) @@ -1018,13 +1018,13 @@ export const toStyles = ( getGapCSSValue( tree?.styles?.spacing?.blockGap ) || '0.5em'; ruleset = ruleset + - `:where(.wp-site-blocks) > * { margin-block-start: ${ gapValue }; margin-block-end: 0; }`; + `:root :where(.wp-site-blocks) > * { margin-block-start: ${ gapValue }; margin-block-end: 0; }`; ruleset = ruleset + - ':where(.wp-site-blocks) > :first-child { margin-block-start: 0; }'; + ':root :where(.wp-site-blocks) > :first-child { margin-block-start: 0; }'; ruleset = ruleset + - ':where(.wp-site-blocks) > :last-child { margin-block-end: 0; }'; + ':root :where(.wp-site-blocks) > :last-child { margin-block-end: 0; }'; } if ( options.presets ) { @@ -1185,7 +1185,7 @@ export function processCSSNesting( css, blockSelector ) { const isRootCss = ! part.includes( '{' ); if ( isRootCss ) { // If the part doesn't contain braces, it applies to the root level. - processedCSS += `${ blockSelector }{${ part.trim() }}`; + processedCSS += `:root :where(${ blockSelector }){${ part.trim() }}`; } else { // If the part contains braces, it's a nested CSS rule. const splittedPart = part.replace( '}', '' ).split( '{' ); @@ -1198,7 +1198,7 @@ export function processCSSNesting( css, blockSelector ) { ? scopeSelector( blockSelector, nestedSelector ) : appendToSelector( blockSelector, nestedSelector ); - processedCSS += `${ combinedSelector }{${ cssValue.trim() }}`; + processedCSS += `:root :where(${ combinedSelector }){${ cssValue.trim() }}`; } } ); return processedCSS; diff --git a/packages/block-library/src/audio/theme.scss b/packages/block-library/src/audio/theme.scss index eda394fd6a3d54..2744d36e74ca62 100644 --- a/packages/block-library/src/audio/theme.scss +++ b/packages/block-library/src/audio/theme.scss @@ -2,6 +2,6 @@ @include caption-style-theme(); } -:where(.wp-block-audio) { +.wp-block-audio { margin: 0 0 1em 0; } diff --git a/packages/block-library/src/button/editor.scss b/packages/block-library/src/button/editor.scss index c24021d17e38ec..8c879c7e3b7c9e 100644 --- a/packages/block-library/src/button/editor.scss +++ b/packages/block-library/src/button/editor.scss @@ -37,38 +37,3 @@ div[data-type="core/button"] { text-decoration: inherit; } -.editor-styles-wrapper .wp-block-button .wp-block-button__link { - // The following styles ensure a default border is applied when the user selects only a border color or style in the editor, - // but no width. They override the `border-width: 0;` applied by core's theme.json via the Elements API button. - &:where(.has-border-color) { - border-width: initial; - } - &:where([style*="border-top-color"]) { - border-top-width: initial; - } - &:where([style*="border-right-color"]) { - border-right-width: initial; - } - &:where([style*="border-bottom-color"]) { - border-bottom-width: initial; - } - &:where([style*="border-left-color"]) { - border-left-width: initial; - } - - &:where([style*="border-style"]) { - border-width: initial; - } - &:where([style*="border-top-style"]) { - border-top-width: initial; - } - &:where([style*="border-right-style"]) { - border-right-width: initial; - } - &:where([style*="border-bottom-style"]) { - border-bottom-width: initial; - } - &:where([style*="border-left-style"]) { - border-left-width: initial; - } -} diff --git a/packages/block-library/src/button/style.scss b/packages/block-library/src/button/style.scss index f441152107973f..42306cba0c984d 100644 --- a/packages/block-library/src/button/style.scss +++ b/packages/block-library/src/button/style.scss @@ -86,69 +86,37 @@ $blocks-block__margin: 0.5em; } } -// the first selector is required for old buttons markup +// The follow block style selectors are required for old buttons markup +// and do not use the `:root :where()` format to match specificity at +// the time they were deprecated. .wp-block-button.is-style-squared, .wp-block-button__link.wp-block-button.is-style-squared { border-radius: 0; } - -// the first selector is required for old buttons markup .wp-block-button.no-border-radius, .wp-block-button__link.no-border-radius { border-radius: 0 !important; } -.wp-block-button:where(.is-style-outline) > .wp-block-button__link, -.wp-block-button .wp-block-button__link:where(.is-style-outline) { - border: 2px solid currentColor; - padding: 0.667em 1.333em; -} - -.wp-block-button:where(.is-style-outline) > .wp-block-button__link:not(.has-text-color), -.wp-block-button .wp-block-button__link:where(.is-style-outline):not(.has-text-color) { - color: currentColor; -} - -.wp-block-button:where(.is-style-outline) > .wp-block-button__link:not(.has-background), -.wp-block-button .wp-block-button__link:where(.is-style-outline):not(.has-background) { - background-color: transparent; - // background-image is required to overwrite a gradient background - background-image: none; -} - -.wp-block-button .wp-block-button__link { - // The following styles ensure a default border is applied when the user - // selects only a border color or style. This overcomes the zero border - // width applied by core's theme.json via the elements API. - &:where(.has-border-color) { - border-width: initial; - } - &:where([style*="border-top-color"]) { - border-top-width: initial; - } - &:where([style*="border-right-color"]) { - border-right-width: initial; - } - &:where([style*="border-bottom-color"]) { - border-bottom-width: initial; - } - &:where([style*="border-left-color"]) { - border-left-width: initial; +// Selectors here use the `:root :where()` format for maintaining compatibility +// with global styles and nested block style variations. +:root { + // Outline Block Style Variation. + :where(.wp-block-button.is-style-outline > .wp-block-button__link), + :where(.wp-block-button .wp-block-button__link.is-style-outline) { + border: 2px solid currentColor; + padding: 0.667em 1.333em; } - &:where([style*="border-style"]) { - border-width: initial; - } - &:where([style*="border-top-style"]) { - border-top-width: initial; + :where(.wp-block-button.is-style-outline > .wp-block-button__link:not(.has-text-color)), + :where(.wp-block-button .wp-block-button__link.is-style-outline:not(.has-text-color)) { + color: currentColor; } - &:where([style*="border-right-style"]) { - border-right-width: initial; - } - &:where([style*="border-bottom-style"]) { - border-bottom-width: initial; - } - &:where([style*="border-left-style"]) { - border-left-width: initial; + + :where(.wp-block-button.is-style-outline > .wp-block-button__link:not(.has-background)), + :where(.wp-block-button .wp-block-button__link.is-style-outline:not(.has-background)) { + background-color: transparent; + // background-image is required to overwrite a gradient background + background-image: none; } } diff --git a/packages/block-library/src/cover/style.scss b/packages/block-library/src/cover/style.scss index d14f606fc0226a..58f1147f12d279 100644 --- a/packages/block-library/src/cover/style.scss +++ b/packages/block-library/src/cover/style.scss @@ -1,11 +1,7 @@ -// Lowest specificity styles are used to ensure that the default styles for the cover block can be overridden by global styles. -:where(.wp-block-cover-image, .wp-block-cover) { - min-height: 430px; - padding: 1em; -} - .wp-block-cover-image, .wp-block-cover { + min-height: 430px; + padding: 1em; position: relative; background-position: center center; display: flex; @@ -120,18 +116,6 @@ /*rtl:raw: direction: rtl; */ } - p, - h1, - h2, - h3, - h4, - h5, - h6 { - &:where(:not(.has-text-color)) { - color: inherit; - } - } - // Position: Top &.is-position-top-left { align-items: flex-start; @@ -314,3 +298,15 @@ section.wp-block-cover-image > h2, :where(.wp-block-cover-image.is-light:not(.has-text-color)) { color: $black; } + +:root { + :where(.wp-block-cover p:not(.has-text-color)), + :where(.wp-block-cover h1:not(.has-text-color)), + :where(.wp-block-cover h2:not(.has-text-color)), + :where(.wp-block-cover h3:not(.has-text-color)), + :where(.wp-block-cover h4:not(.has-text-color)), + :where(.wp-block-cover h5:not(.has-text-color)), + :where(.wp-block-cover h6:not(.has-text-color)) { + color: inherit; + } +} diff --git a/packages/block-library/src/embed/theme.scss b/packages/block-library/src/embed/theme.scss index 57ece1dcd43cac..e809a783b9c810 100644 --- a/packages/block-library/src/embed/theme.scss +++ b/packages/block-library/src/embed/theme.scss @@ -2,6 +2,6 @@ @include caption-style-theme(); } -:where(.wp-block-embed) { +.wp-block-embed { margin: 0 0 1em 0; } diff --git a/packages/block-library/src/gallery/editor.scss b/packages/block-library/src/gallery/editor.scss index ea6fa8836a3a4b..9efaf88e5acc71 100644 --- a/packages/block-library/src/gallery/editor.scss +++ b/packages/block-library/src/gallery/editor.scss @@ -1,4 +1,7 @@ -:where(figure.wp-block-gallery) { +// Adding `figure` to the selector increases the specificity above the global +// styles specificity, which is levelled at 0-1-0. We should figure out why +// `figure` is needed. +:root :where(figure.wp-block-gallery) { // Override the default list style type _only in the editor_ // to avoid :not() selector specificity issues. // See https://github.com/WordPress/gutenberg/pull/10358 diff --git a/packages/block-library/src/image/style.scss b/packages/block-library/src/image/style.scss index 75c8b839dca37c..40ffe0cd0e61c7 100644 --- a/packages/block-library/src/image/style.scss +++ b/packages/block-library/src/image/style.scss @@ -82,16 +82,10 @@ @include caption-style(); } - // Variations - &.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; - } - // The following variation is deprecated. // The CSS is kept here for the time being, to support blocks using the old variation. + // The selector is not scoped with `:root :where()` like global styles are to keep its + // specificity the same as it was when it was deprecated. &.is-style-circle-mask 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. @@ -108,42 +102,13 @@ border-radius: 0; } } +} - // The following is required to overcome WP Core applying styles that clear - // img borders with a higher specificity than those added by the border - // block support to provide a default border-style of solid when a border - // color or width has been set. - :where(.has-border-color) { - border-style: solid; - } - :where([style*="border-top-color"]) { - border-top-style: solid; - } - :where([style*="border-right-color"]) { - border-right-style: solid; - } - :where([style*="border-bottom-color"]) { - border-bottom-style: solid; - } - :where([style*="border-left-color"]) { - border-left-style: solid; - } - - :where([style*="border-width"]) { - border-style: solid; - } - :where([style*="border-top-width"]) { - border-top-style: solid; - } - :where([style*="border-right-width"]) { - border-right-style: solid; - } - :where([style*="border-bottom-width"]) { - border-bottom-style: solid; - } - :where([style*="border-left-width"]) { - border-left-style: solid; - } +// Variations +:root :where(.wp-block-image.is-style-rounded img, .wp-block-image .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; } .wp-block-image figure { diff --git a/packages/block-library/src/image/theme.scss b/packages/block-library/src/image/theme.scss index 459036511335a6..c89dd3334dd09a 100644 --- a/packages/block-library/src/image/theme.scss +++ b/packages/block-library/src/image/theme.scss @@ -1,7 +1,7 @@ -.wp-block-image figcaption { +:root :where(.wp-block-image figcaption) { @include caption-style-theme(); } -:where(.wp-block-image) { +.wp-block-image { margin: 0 0 1em 0; } diff --git a/packages/block-library/src/latest-posts/editor.scss b/packages/block-library/src/latest-posts/editor.scss index 3c2d6a30f1c077..a963ab531597c6 100644 --- a/packages/block-library/src/latest-posts/editor.scss +++ b/packages/block-library/src/latest-posts/editor.scss @@ -1,9 +1,4 @@ .wp-block-latest-posts { - padding-left: 2.5em; - &.is-grid { - padding-left: 0; - } - // Apply overflow for post items, so any floated featured images won't crop the focus style. > li { overflow: hidden; @@ -27,3 +22,13 @@ border-radius: $radius-block-ui; } } + +:root :where(.wp-block-latest-posts) { + padding-left: 2.5em; +} +:root { + :where(.wp-block-latest-posts.is-grid), + :where(.wp-block-latest-posts__list) { + padding-left: 0; + } +} diff --git a/packages/block-library/src/latest-posts/style.scss b/packages/block-library/src/latest-posts/style.scss index 5d3e360d0804a8..2a01d177ef47c4 100644 --- a/packages/block-library/src/latest-posts/style.scss +++ b/packages/block-library/src/latest-posts/style.scss @@ -12,7 +12,6 @@ } &.wp-block-latest-posts__list { list-style: none; - padding-left: 0; li { clear: both; @@ -23,7 +22,6 @@ &.is-grid { display: flex; flex-wrap: wrap; - padding: 0; li { margin: 0 1.25em 1.25em 0; @@ -34,9 +32,9 @@ @include break-small { @for $i from 2 through 6 { &.columns-#{ $i } li { - width: calc((100% / #{ $i }) - 1.25em + (1.25em / #{ $i })); + width: calc((100% / #{$i}) - 1.25em + (1.25em / #{$i})); - &:nth-child( #{ $i }n ) { + &:nth-child(#{ $i }n) { margin-right: 0; } } @@ -44,6 +42,15 @@ } } +:root { + :where(.wp-block-latest-posts.is-grid) { + padding: 0; + } + :where(.wp-block-latest-posts.wp-block-latest-posts__list) { + padding-left: 0; + } +} + .wp-block-latest-posts__post-date, .wp-block-latest-posts__post-author { display: block; diff --git a/packages/block-library/src/pullquote/editor.scss b/packages/block-library/src/pullquote/editor.scss index 7b985d8020c9fe..deb325849ebebf 100644 --- a/packages/block-library/src/pullquote/editor.scss +++ b/packages/block-library/src/pullquote/editor.scss @@ -1,4 +1,6 @@ // .is-style-solid-color is deprecated. +// This selector has not been scoped with `:root :where`, as global styles +// does, to keep its specificity as it was at the time of deprecation. .wp-block-pullquote.is-style-solid-color { & blockquote p { font-size: 32px; diff --git a/packages/block-library/src/pullquote/style.scss b/packages/block-library/src/pullquote/style.scss index 07f6366d47617f..b9e28b7cdcfaa6 100644 --- a/packages/block-library/src/pullquote/style.scss +++ b/packages/block-library/src/pullquote/style.scss @@ -2,6 +2,8 @@ text-align: center; // Default text-alignment where the `textAlign` attribute value isn't specified. overflow-wrap: break-word; // Break long strings of text without spaces so they don't overflow the block. box-sizing: border-box; + margin: 0 0 1em 0; + padding: 4em 0; p, blockquote, @@ -35,12 +37,6 @@ } } -// Lowest specificity to avoid overriding layout and global styles. -:where(.wp-block-pullquote) { - margin: 0 0 1em 0; - padding: 4em 0; -} - // Ensure that we are reasonably specific to override theme defaults. .wp-block-pullquote.has-text-align-left blockquote { text-align: left; @@ -52,6 +48,8 @@ } // .is-style-solid-color is deprecated. +// This selector has not been scoped with `:root :where`, as global styles +// does, to keep its specificity as it was at the time of deprecation. .wp-block-pullquote.is-style-solid-color { border: none; blockquote { diff --git a/packages/block-library/src/pullquote/theme.scss b/packages/block-library/src/pullquote/theme.scss index 0dc7943a770512..6b5e8401227f5b 100644 --- a/packages/block-library/src/pullquote/theme.scss +++ b/packages/block-library/src/pullquote/theme.scss @@ -1,11 +1,9 @@ -:where(.wp-block-pullquote) { +.wp-block-pullquote { border-top: 4px solid currentColor; border-bottom: 4px solid currentColor; margin-bottom: 1.75em; color: currentColor; -} -.wp-block-pullquote { cite, footer, &__citation { diff --git a/packages/block-library/src/quote/theme.scss b/packages/block-library/src/quote/theme.scss index aaf63b899771b0..5bcccbd60eefc4 100644 --- a/packages/block-library/src/quote/theme.scss +++ b/packages/block-library/src/quote/theme.scss @@ -1,4 +1,4 @@ -:where(.wp-block-quote) { +.wp-block-quote { border-left: 0.25em solid currentColor; margin: 0 0 1.75em 0; padding-left: 1em; diff --git a/packages/block-library/src/separator/editor.scss b/packages/block-library/src/separator/editor.scss index 220c6bd9d80e38..24e940684279e8 100644 --- a/packages/block-library/src/separator/editor.scss +++ b/packages/block-library/src/separator/editor.scss @@ -2,11 +2,4 @@ // Prevent margin collapsing so the area to select the separator is bigger. padding-top: 0.1px; padding-bottom: 0.1px; - - // This is also set in style.scss, but needs a higher specificity in editor - // due to the way that color block supports adds additional background color styles. - &.wp-block-separator.is-style-dots { - background: none !important; - border: none; - } } diff --git a/packages/block-library/src/separator/style.scss b/packages/block-library/src/separator/style.scss index d40dd2f05844ed..65e463bc513f48 100644 --- a/packages/block-library/src/separator/style.scss +++ b/packages/block-library/src/separator/style.scss @@ -1,28 +1,4 @@ .wp-block-separator { - // Dots style - &.is-style-dots { - // Override any background themes often set on the hr tag for this style. - // also override the color set in the editor since it's intented for normal HR - background: none !important; - border: none; - text-align: center; - line-height: 1; - height: auto; - - &::before { - content: "\00b7 \00b7 \00b7"; - color: currentColor; - font-size: 1.5em; - letter-spacing: 2em; - /*rtl:ignore*/ - padding-left: 2em; - font-family: serif; - } - } -} - -// Lowest specificity to avoid overriding global styles. -:where(.wp-block-separator) { border-top: 2px solid currentColor; // Default, thin style, is stored in theme.scss so it can be opted out of @@ -31,3 +7,31 @@ border-right: none; border-bottom: none; } + +// Dots block style variation +:root :where(.wp-block-separator.is-style-dots) { + text-align: center; + line-height: 1; + height: auto; + + &::before { + content: "\00b7 \00b7 \00b7"; + color: currentColor; + font-size: 1.5em; + letter-spacing: 2em; + /*rtl:ignore*/ + padding-left: 2em; + font-family: serif; + } +} + +// The following overrides should be enforced regardless of global styles. +// The dots block style uses a pseudo element to render the dots. Background +// color and borders would break this aesthetic. +.wp-block-separator.is-style-dots { + // Override any background themes often set on the hr tag for this style. + // also override the color set in the editor since it's intended for normal HR + background: none !important; + // Important required to ensure dots does not get a border. + border: none !important; +} diff --git a/packages/block-library/src/site-logo/style.scss b/packages/block-library/src/site-logo/style.scss index ca9c92539b6760..020b7aab5370b3 100644 --- a/packages/block-library/src/site-logo/style.scss +++ b/packages/block-library/src/site-logo/style.scss @@ -31,11 +31,11 @@ margin-right: auto; text-align: center; } +} - // Style variations - &.is-style-rounded { - // 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; - } +// Style variations +:root :where(.wp-block-site-logo.is-style-rounded) { + // 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; } diff --git a/packages/block-library/src/site-title/editor.scss b/packages/block-library/src/site-title/editor.scss index 173e4570929a51..ce83659170ff6f 100644 --- a/packages/block-library/src/site-title/editor.scss +++ b/packages/block-library/src/site-title/editor.scss @@ -3,8 +3,6 @@ border: 1px dashed; } -.editor-styles-wrapper .wp-block-site-title { - a { - color: inherit; - } +.editor-styles-wrapper :where(.wp-block-site-title a) { + color: inherit; } diff --git a/packages/block-library/src/site-title/style.scss b/packages/block-library/src/site-title/style.scss index afc6f449f4025b..337c82f79ad354 100644 --- a/packages/block-library/src/site-title/style.scss +++ b/packages/block-library/src/site-title/style.scss @@ -1,5 +1,3 @@ -.wp-block-site-title { - a { - color: inherit; - } +:root :where(.wp-block-site-title a) { + color: inherit; } diff --git a/packages/block-library/src/social-link/editor.scss b/packages/block-library/src/social-link/editor.scss index 73211958b48c15..bd93ad9f055fcd 100644 --- a/packages/block-library/src/social-link/editor.scss +++ b/packages/block-library/src/social-link/editor.scss @@ -31,11 +31,11 @@ } } -.wp-block-social-links.is-style-pill-shape .wp-social-link button { +:root :where(.wp-block-social-links.is-style-pill-shape .wp-social-link button) { padding-left: calc((2/3) * 1em); padding-right: calc((2/3) * 1em); } -.wp-block-social-links.is-style-logos-only .wp-social-link button { +:root :where(.wp-block-social-links.is-style-logos-only .wp-social-link button) { padding: 0; } diff --git a/packages/block-library/src/social-links/editor.scss b/packages/block-library/src/social-links/editor.scss index b729949c837d80..6f07ea209ecbea 100644 --- a/packages/block-library/src/social-links/editor.scss +++ b/packages/block-library/src/social-links/editor.scss @@ -11,9 +11,19 @@ transform: none; } -.editor-styles-wrapper .wp-block-social-links { +// Specificity for the following styles are fixed at 0-1-0 to match and be +// overridable by global styles. +:root :where(.wp-block-social-links), +:root :where(.wp-block-social-links.is-style-logos-only .wp-block-social-links__social-placeholder .wp-social-link) { padding: 0; } +:root :where(.wp-block-social-links__social-placeholder .wp-social-link) { + padding: 0.25em; +} +:root :where(.wp-block-social-links.is-style-pill-shape .wp-block-social-links__social-placeholder .wp-social-link) { + padding-left: calc((2/3) * 1em); + padding-right: calc((2/3) * 1em); +} // Placeholder/setup state. .wp-block-social-links__social-placeholder { @@ -37,19 +47,6 @@ display: flex; } - .wp-social-link { - padding: 0.25em; - - .is-style-pill-shape & { - padding-left: calc((2/3) * 1em); - padding-right: calc((2/3) * 1em); - } - - .is-style-logos-only & { - padding: 0; - } - } - .wp-social-link::before { content: ""; display: block; diff --git a/packages/block-library/src/social-links/style.scss b/packages/block-library/src/social-links/style.scss index 1ad883bbb88840..f04c11ea07acd3 100644 --- a/packages/block-library/src/social-links/style.scss +++ b/packages/block-library/src/social-links/style.scss @@ -21,12 +21,6 @@ } .wp-social-link { - // By setting the font size, we can scale icons and paddings consistently based on that. - // This also allows themes to override this, if need be. - a { - padding: 0.25em; - } - svg { width: 1em; height: 1em; @@ -119,14 +113,13 @@ } // Treatment for logos only style. +// The specificity for this selector has not been reduced to 0-1-0 as per +// global styles variation selectors as the lack of background should be +// enforced for this block style. .wp-block-social-links.is-style-logos-only { .wp-social-link { background: none; - a { - padding: 0; - } - // Make these bigger. svg { width: 1.25em; @@ -142,11 +135,19 @@ .wp-social-link { width: auto; } +} - .wp-social-link a { - padding-left: calc((2/3) * 1em); - padding-right: calc((2/3) * 1em); - } +// The following rules have their selector specificity set to 0-1-0 to +// facilitate theme.json styling of the inner social-link block padding. +:root :where(.wp-block-social-links .wp-social-link a) { + padding: 0.25em; +} +:root :where(.wp-block-social-links.is-style-logos-only .wp-social-link a) { + padding: 0; +} +:root :where(.wp-block-social-links.is-style-pill-shape .wp-social-link a) { + padding-left: calc((2/3) * 1em); + padding-right: calc((2/3) * 1em); } // Ensure the Snapchat label is visible when no custom diff --git a/packages/block-library/src/table/style.scss b/packages/block-library/src/table/style.scss index 4f4271650f50e1..69cd2666e13e20 100644 --- a/packages/block-library/src/table/style.scss +++ b/packages/block-library/src/table/style.scss @@ -71,6 +71,9 @@ } // "Stripes" style variation. + // This block style selector does not have 0-1-0 specificity, as per those + // generated via global styles, to maintain current styling. Global styles + // support for table borders also only applies to the outer `table` element. &.is-style-stripes { border-spacing: 0; border-collapse: inherit; diff --git a/packages/block-library/src/table/theme.scss b/packages/block-library/src/table/theme.scss index 19dc71c8857bd7..d42e79b02b4965 100644 --- a/packages/block-library/src/table/theme.scss +++ b/packages/block-library/src/table/theme.scss @@ -1,4 +1,6 @@ .wp-block-table { + margin: 0 0 1em 0; + td, th { word-break: normal; @@ -8,7 +10,3 @@ @include caption-style-theme(); } } - -:where(.wp-block-table) { - margin: 0 0 1em 0; -} diff --git a/packages/block-library/src/tag-cloud/style.scss b/packages/block-library/src/tag-cloud/style.scss index 5fb04840de1517..dedb5e73ab1a1f 100644 --- a/packages/block-library/src/tag-cloud/style.scss +++ b/packages/block-library/src/tag-cloud/style.scss @@ -22,18 +22,20 @@ margin-left: 5px; text-decoration: none; } +} - &.is-style-outline { - display: flex; - flex-wrap: wrap; - gap: 1ch; - - a { - border: 1px solid currentColor; - font-size: unset !important; // !important Needed to override the inline styles. - margin-right: 0; - padding: 1ch 2ch; - text-decoration: none !important; // !important needed to override generic post content link decoration. - } - } +// Specificity is set to 0-1-0 to match global styles selectors. +:root :where(.wp-block-tag-cloud.is-style-outline) { + display: flex; + flex-wrap: wrap; + gap: 1ch; +} +// The block support related styles below haven't been replicated in the base theme.json +// as the block doesn't yet adopt them for its inner links. +:root :where(.wp-block-tag-cloud.is-style-outline a) { + border: 1px solid currentColor; + font-size: unset !important; // !important Needed to override the inline styles. + margin-right: 0; + padding: 1ch 2ch; + text-decoration: none !important; // !important needed to override generic post content link decoration. } diff --git a/packages/block-library/src/template-part/theme.scss b/packages/block-library/src/template-part/theme.scss index 2f1d3a0a513cb7..179873b9448b82 100644 --- a/packages/block-library/src/template-part/theme.scss +++ b/packages/block-library/src/template-part/theme.scss @@ -1,9 +1,7 @@ // Same as the group block styles. -:where(.wp-block-template-part) { - &.has-background { - // Matches paragraph Block padding - padding: $block-bg-padding--v $block-bg-padding--h; - margin-top: 0; - margin-bottom: 0; - } +:root :where(.wp-block-template-part.has-background) { + // Matches paragraph Block padding + padding: $block-bg-padding--v $block-bg-padding--h; + margin-top: 0; + margin-bottom: 0; } diff --git a/packages/block-library/src/video/theme.scss b/packages/block-library/src/video/theme.scss index c5399582bbb281..cdc95af0b02c29 100644 --- a/packages/block-library/src/video/theme.scss +++ b/packages/block-library/src/video/theme.scss @@ -2,6 +2,6 @@ @include caption-style-theme(); } -:where(.wp-block-video) { +.wp-block-video { margin: 0 0 1em 0; } diff --git a/phpunit/class-wp-theme-json-test.php b/phpunit/class-wp-theme-json-test.php index 00799b7ba0b478..aed3e9963ac25b 100644 --- a/phpunit/class-wp-theme-json-test.php +++ b/phpunit/class-wp-theme-json-test.php @@ -547,7 +547,7 @@ public function test_get_stylesheet() { ); $variables = ':root{--wp--preset--color--grey: grey;--wp--preset--gradient--custom-gradient: linear-gradient(135deg,rgba(0,0,0) 0%,rgb(0,0,0) 100%);--wp--preset--font-size--small: 14px;--wp--preset--font-size--big: 41px;--wp--preset--font-family--arial: Arial, serif;}.wp-block-group{--wp--custom--base-font: 16;--wp--custom--line-height--small: 1.2;--wp--custom--line-height--medium: 1.4;--wp--custom--line-height--large: 1.8;}'; - $styles = static::$base_styles . ':where(body){color: var(--wp--preset--color--grey);}:where(a:where(:not(.wp-element-button))){background-color: #333;color: #111;}:where(.wp-element-button, .wp-block-button__link){box-shadow: 10px 10px 5px 0px rgba(0,0,0,0.66);}:where(.wp-block-cover){min-height: unset;aspect-ratio: 16/9;}:where(.wp-block-group){background: var(--wp--preset--gradient--custom-gradient);border-radius: 10px;min-height: 50vh;padding: 24px;}:where(.wp-block-group a:where(:not(.wp-element-button))){color: #111;}:where(.wp-block-heading){color: #123456;}:where(.wp-block-heading a:where(:not(.wp-element-button))){background-color: #333;color: #111;font-size: 60px;}:where(.wp-block-post-date){color: #123456;}:where(.wp-block-post-date a:where(:not(.wp-element-button))){background-color: #777;color: #555;}:where(.wp-block-post-excerpt){column-count: 2;}:where(.wp-block-image){margin-bottom: 30px;}:where(.wp-block-image img, .wp-block-image .wp-block-image__crop-area, .wp-block-image .components-placeholder){border-top-left-radius: 10px;border-bottom-right-radius: 1em;}:where(.wp-block-image img, .wp-block-image .components-placeholder){filter: var(--wp--preset--duotone--custom-duotone);}'; + $styles = static::$base_styles . ':root :where(body){color: var(--wp--preset--color--grey);}:root :where(a:where(:not(.wp-element-button))){background-color: #333;color: #111;}:root :where(.wp-element-button, .wp-block-button__link){box-shadow: 10px 10px 5px 0px rgba(0,0,0,0.66);}:root :where(.wp-block-cover){min-height: unset;aspect-ratio: 16/9;}:root :where(.wp-block-group){background: var(--wp--preset--gradient--custom-gradient);border-radius: 10px;min-height: 50vh;padding: 24px;}:root :where(.wp-block-group a:where(:not(.wp-element-button))){color: #111;}:root :where(.wp-block-heading){color: #123456;}:root :where(.wp-block-heading a:where(:not(.wp-element-button))){background-color: #333;color: #111;font-size: 60px;}:root :where(.wp-block-post-date){color: #123456;}:root :where(.wp-block-post-date a:where(:not(.wp-element-button))){background-color: #777;color: #555;}:root :where(.wp-block-post-excerpt){column-count: 2;}:root :where(.wp-block-image){margin-bottom: 30px;}:root :where(.wp-block-image img, .wp-block-image .wp-block-image__crop-area, .wp-block-image .components-placeholder){border-top-left-radius: 10px;border-bottom-right-radius: 1em;}:root :where(.wp-block-image img, .wp-block-image .components-placeholder){filter: var(--wp--preset--duotone--custom-duotone);}'; $presets = '.has-grey-color{color: var(--wp--preset--color--grey) !important;}.has-grey-background-color{background-color: var(--wp--preset--color--grey) !important;}.has-grey-border-color{border-color: var(--wp--preset--color--grey) !important;}.has-custom-gradient-gradient-background{background: var(--wp--preset--gradient--custom-gradient) !important;}.has-small-font-size{font-size: var(--wp--preset--font-size--small) !important;}.has-big-font-size{font-size: var(--wp--preset--font-size--big) !important;}.has-arial-font-family{font-family: var(--wp--preset--font-family--arial) !important;}'; $all = $variables . $styles . $presets; @@ -593,7 +593,7 @@ public function test_get_stylesheet_support_for_shorthand_and_longhand_values() ) ); - $styles = static::$base_styles . ':where(.wp-block-group){border-radius: 10px;margin: 1em;padding: 24px;}:where(.wp-block-image){margin-bottom: 30px;padding-top: 15px;}:where(.wp-block-image img, .wp-block-image .wp-block-image__crop-area, .wp-block-image .components-placeholder){border-top-left-radius: 10px;border-bottom-right-radius: 1em;}'; + $styles = static::$base_styles . ':root :where(.wp-block-group){border-radius: 10px;margin: 1em;padding: 24px;}:root :where(.wp-block-image){margin-bottom: 30px;padding-top: 15px;}:root :where(.wp-block-image img, .wp-block-image .wp-block-image__crop-area, .wp-block-image .components-placeholder){border-top-left-radius: 10px;border-bottom-right-radius: 1em;}'; $this->assertSame( $styles, $theme_json->get_stylesheet() ); $this->assertSame( $styles, $theme_json->get_stylesheet( array( 'styles' ) ) ); } @@ -644,7 +644,7 @@ public function test_get_stylesheet_renders_enabled_protected_properties() { ) ); - $expected = ':where(body) { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.wp-site-blocks) > * { margin-block-start: 1em; margin-block-end: 0; }:where(.wp-site-blocks) > :first-child { margin-block-start: 0; }:where(.wp-site-blocks) > :last-child { margin-block-end: 0; }:root { --wp--style--block-gap: 1em; }:where(.is-layout-flow) > :first-child{margin-block-start: 0;}:where(.is-layout-flow) > :last-child{margin-block-end: 0;}:where(.is-layout-flow) > *{margin-block-start: 1em;margin-block-end: 0;}:where(.is-layout-constrained) > :first-child{margin-block-start: 0;}:where(.is-layout-constrained) > :last-child{margin-block-end: 0;}:where(.is-layout-constrained) > *{margin-block-start: 1em;margin-block-end: 0;}:where(.is-layout-flex) {gap: 1em;}:where(.is-layout-grid) {gap: 1em;}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){margin-left: auto !important;margin-right: auto !important;}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}'; + $expected = ':where(body) { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.wp-site-blocks) > * { margin-block-start: 1em; margin-block-end: 0; }:where(.wp-site-blocks) > :first-child { margin-block-start: 0; }:where(.wp-site-blocks) > :last-child { margin-block-end: 0; }:root { --wp--style--block-gap: 1em; }.is-layout-flow > :first-child{margin-block-start: 0;}.is-layout-flow > :last-child{margin-block-end: 0;}.is-layout-flow > *{margin-block-start: 1em;margin-block-end: 0;}.is-layout-constrained > :first-child{margin-block-start: 0;}.is-layout-constrained > :last-child{margin-block-end: 0;}.is-layout-constrained > *{margin-block-start: 1em;margin-block-end: 0;}.is-layout-flex {gap: 1em;}.is-layout-grid {gap: 1em;}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){margin-left: auto !important;margin-right: auto !important;}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}'; $this->assertSame( $expected, $theme_json->get_stylesheet() ); $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles' ) ) ); } @@ -706,7 +706,7 @@ public function test_get_stylesheet_preset_rules_come_after_block_rules() { ) ); - $styles = static::$base_styles . ':where(.wp-block-group){color: red;}'; + $styles = static::$base_styles . ':root :where(.wp-block-group){color: red;}'; $presets = '.wp-block-group.has-grey-color{color: var(--wp--preset--color--grey) !important;}.wp-block-group.has-grey-background-color{background-color: var(--wp--preset--color--grey) !important;}.wp-block-group.has-grey-border-color{border-color: var(--wp--preset--color--grey) !important;}'; $variables = '.wp-block-group{--wp--preset--color--grey: grey;}'; @@ -793,7 +793,7 @@ public function test_get_stylesheet_preset_values_are_marked_as_important() { ); $this->assertSame( - ':root{--wp--preset--color--grey: grey;}' . static::$base_styles . ':where(p){background-color: blue;color: red;font-size: 12px;line-height: 1.3;}.has-grey-color{color: var(--wp--preset--color--grey) !important;}.has-grey-background-color{background-color: var(--wp--preset--color--grey) !important;}.has-grey-border-color{border-color: var(--wp--preset--color--grey) !important;}', + ':root{--wp--preset--color--grey: grey;}' . static::$base_styles . ':root :where(p){background-color: blue;color: red;font-size: 12px;line-height: 1.3;}.has-grey-color{color: var(--wp--preset--color--grey) !important;}.has-grey-background-color{background-color: var(--wp--preset--color--grey) !important;}.has-grey-border-color{border-color: var(--wp--preset--color--grey) !important;}', $theme_json->get_stylesheet() ); } @@ -831,7 +831,7 @@ public function test_get_stylesheet_handles_whitelisted_element_pseudo_selectors ) ); - $element_styles = ':where(a:where(:not(.wp-element-button))){background-color: red;color: green;}:where(a:where(:not(.wp-element-button)):hover){background-color: green;color: red;font-size: 10em;text-transform: uppercase;}:where(a:where(:not(.wp-element-button)):focus){background-color: black;color: yellow;}'; + $element_styles = ':root :where(a:where(:not(.wp-element-button))){background-color: red;color: green;}:root :where(a:where(:not(.wp-element-button)):hover){background-color: green;color: red;font-size: 10em;text-transform: uppercase;}:root :where(a:where(:not(.wp-element-button)):focus){background-color: black;color: yellow;}'; $expected = static::$base_styles . $element_styles; @@ -868,7 +868,7 @@ public function test_get_stylesheet_handles_only_pseudo_selector_rules_for_given ) ); - $element_styles = ':where(a:where(:not(.wp-element-button)):hover){background-color: green;color: red;font-size: 10em;text-transform: uppercase;}:where(a:where(:not(.wp-element-button)):focus){background-color: black;color: yellow;}'; + $element_styles = ':root :where(a:where(:not(.wp-element-button)):hover){background-color: green;color: red;font-size: 10em;text-transform: uppercase;}:root :where(a:where(:not(.wp-element-button)):focus){background-color: black;color: yellow;}'; $expected = static::$base_styles . $element_styles; @@ -905,7 +905,7 @@ public function test_get_stylesheet_ignores_pseudo_selectors_on_non_whitelisted_ ) ); - $element_styles = ':where(h4){background-color: red;color: green;}'; + $element_styles = ':root :where(h4){background-color: red;color: green;}'; $expected = static::$base_styles . $element_styles; @@ -942,7 +942,7 @@ public function test_get_stylesheet_ignores_non_whitelisted_pseudo_selectors() { ) ); - $element_styles = ':where(a:where(:not(.wp-element-button))){background-color: red;color: green;}:where(a:where(:not(.wp-element-button)):hover){background-color: green;color: red;}'; + $element_styles = ':root :where(a:where(:not(.wp-element-button))){background-color: red;color: green;}:root :where(a:where(:not(.wp-element-button)):hover){background-color: green;color: red;}'; $expected = static::$base_styles . $element_styles; @@ -988,7 +988,7 @@ public function test_get_stylesheet_handles_priority_of_elements_vs_block_elemen ) ); - $element_styles = ':where(.wp-block-group a:where(:not(.wp-element-button))){background-color: red;color: green;}:where(.wp-block-group a:where(:not(.wp-element-button)):hover){background-color: green;color: red;font-size: 10em;text-transform: uppercase;}:where(.wp-block-group a:where(:not(.wp-element-button)):focus){background-color: black;color: yellow;}'; + $element_styles = ':root :where(.wp-block-group a:where(:not(.wp-element-button))){background-color: red;color: green;}:root :where(.wp-block-group a:where(:not(.wp-element-button)):hover){background-color: green;color: red;font-size: 10em;text-transform: uppercase;}:root :where(.wp-block-group a:where(:not(.wp-element-button)):focus){background-color: black;color: yellow;}'; $expected = static::$base_styles . $element_styles; @@ -1033,7 +1033,7 @@ public function test_get_stylesheet_handles_whitelisted_block_level_element_pseu ) ); - $element_styles = ':where(a:where(:not(.wp-element-button))){background-color: red;color: green;}:where(a:where(:not(.wp-element-button)):hover){background-color: green;color: red;}:where(.wp-block-group a:where(:not(.wp-element-button)):hover){background-color: black;color: yellow;}'; + $element_styles = ':root :where(a:where(:not(.wp-element-button))){background-color: red;color: green;}:root :where(a:where(:not(.wp-element-button)):hover){background-color: green;color: red;}:root :where(.wp-block-group a:where(:not(.wp-element-button)):hover){background-color: black;color: yellow;}'; $expected = static::$base_styles . $element_styles; @@ -1095,7 +1095,7 @@ public function test_get_stylesheet_with_deprecated_feature_level_selectors() { ); $base_styles = ':root{--wp--preset--color--green: green;}' . static::$base_styles; - $block_styles = ':where(.wp-block-test, .wp-block-test__wrapper){color: green;}:where(.wp-block-test .inner, .wp-block-test__wrapper .inner){border-radius: 9999px;padding: 20px;}:where(.wp-block-test .sub-heading, .wp-block-test__wrapper .sub-heading){font-size: 3em;}'; + $block_styles = ':root :where(.wp-block-test, .wp-block-test__wrapper){color: green;}:root :where(.wp-block-test .inner, .wp-block-test__wrapper .inner){border-radius: 9999px;padding: 20px;}:root :where(.wp-block-test .sub-heading, .wp-block-test__wrapper .sub-heading){font-size: 3em;}'; $preset_styles = '.has-green-color{color: var(--wp--preset--color--green) !important;}.has-green-background-color{background-color: var(--wp--preset--color--green) !important;}.has-green-border-color{border-color: var(--wp--preset--color--green) !important;}'; $expected = $base_styles . $block_styles . $preset_styles; @@ -1157,7 +1157,7 @@ public function test_get_stylesheet_with_block_json_selectors() { ); $base_styles = ':root{--wp--preset--color--green: green;}' . static::$base_styles; - $block_styles = ':where(.custom-root-selector){background-color: grey;padding: 20px;}:where(.custom-root-selector img){border-radius: 9999px;}:where(.custom-root-selector > figcaption){color: navy;font-size: 3em;}'; + $block_styles = ':root :where(.custom-root-selector){background-color: grey;padding: 20px;}:root :where(.custom-root-selector img){border-radius: 9999px;}:root :where(.custom-root-selector > figcaption){color: navy;font-size: 3em;}'; $preset_styles = '.has-green-color{color: var(--wp--preset--color--green) !important;}.has-green-background-color{background-color: var(--wp--preset--color--green) !important;}.has-green-border-color{border-color: var(--wp--preset--color--green) !important;}'; $expected = $base_styles . $block_styles . $preset_styles; @@ -1188,7 +1188,7 @@ public function test_get_stylesheet_generates_layout_styles() { // Results also include root site blocks styles. $this->assertSame( - ':root { --wp--style--global--content-size: 640px;--wp--style--global--wide-size: 1200px; }:where(body) { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.wp-site-blocks) > * { margin-block-start: 1em; margin-block-end: 0; }:where(.wp-site-blocks) > :first-child { margin-block-start: 0; }:where(.wp-site-blocks) > :last-child { margin-block-end: 0; }:root { --wp--style--block-gap: 1em; }:where(.is-layout-flow) > :first-child{margin-block-start: 0;}:where(.is-layout-flow) > :last-child{margin-block-end: 0;}:where(.is-layout-flow) > *{margin-block-start: 1em;margin-block-end: 0;}:where(.is-layout-constrained) > :first-child{margin-block-start: 0;}:where(.is-layout-constrained) > :last-child{margin-block-end: 0;}:where(.is-layout-constrained) > *{margin-block-start: 1em;margin-block-end: 0;}:where(.is-layout-flex) {gap: 1em;}:where(.is-layout-grid) {gap: 1em;}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){max-width: var(--wp--style--global--content-size);margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignwide{max-width: var(--wp--style--global--wide-size);}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}', + ':root { --wp--style--global--content-size: 640px;--wp--style--global--wide-size: 1200px; }:where(body) { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.wp-site-blocks) > * { margin-block-start: 1em; margin-block-end: 0; }:where(.wp-site-blocks) > :first-child { margin-block-start: 0; }:where(.wp-site-blocks) > :last-child { margin-block-end: 0; }:root { --wp--style--block-gap: 1em; }.is-layout-flow > :first-child{margin-block-start: 0;}.is-layout-flow > :last-child{margin-block-end: 0;}.is-layout-flow > *{margin-block-start: 1em;margin-block-end: 0;}.is-layout-constrained > :first-child{margin-block-start: 0;}.is-layout-constrained > :last-child{margin-block-end: 0;}.is-layout-constrained > *{margin-block-start: 1em;margin-block-end: 0;}.is-layout-flex {gap: 1em;}.is-layout-grid {gap: 1em;}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){max-width: var(--wp--style--global--content-size);margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignwide{max-width: var(--wp--style--global--wide-size);}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}', $theme_json->get_stylesheet( array( 'styles' ) ) ); } @@ -1217,7 +1217,7 @@ public function test_get_stylesheet_generates_layout_styles_with_spacing_presets // Results also include root site blocks styles. $this->assertSame( - ':root { --wp--style--global--content-size: 640px;--wp--style--global--wide-size: 1200px; }:where(body) { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.wp-site-blocks) > * { margin-block-start: var(--wp--preset--spacing--60); margin-block-end: 0; }:where(.wp-site-blocks) > :first-child { margin-block-start: 0; }:where(.wp-site-blocks) > :last-child { margin-block-end: 0; }:root { --wp--style--block-gap: var(--wp--preset--spacing--60); }:where(.is-layout-flow) > :first-child{margin-block-start: 0;}:where(.is-layout-flow) > :last-child{margin-block-end: 0;}:where(.is-layout-flow) > *{margin-block-start: var(--wp--preset--spacing--60);margin-block-end: 0;}:where(.is-layout-constrained) > :first-child{margin-block-start: 0;}:where(.is-layout-constrained) > :last-child{margin-block-end: 0;}:where(.is-layout-constrained) > *{margin-block-start: var(--wp--preset--spacing--60);margin-block-end: 0;}:where(.is-layout-flex) {gap: var(--wp--preset--spacing--60);}:where(.is-layout-grid) {gap: var(--wp--preset--spacing--60);}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){max-width: var(--wp--style--global--content-size);margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignwide{max-width: var(--wp--style--global--wide-size);}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}', + ':root { --wp--style--global--content-size: 640px;--wp--style--global--wide-size: 1200px; }:where(body) { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.wp-site-blocks) > * { margin-block-start: var(--wp--preset--spacing--60); margin-block-end: 0; }:where(.wp-site-blocks) > :first-child { margin-block-start: 0; }:where(.wp-site-blocks) > :last-child { margin-block-end: 0; }:root { --wp--style--block-gap: var(--wp--preset--spacing--60); }.is-layout-flow > :first-child{margin-block-start: 0;}.is-layout-flow > :last-child{margin-block-end: 0;}.is-layout-flow > *{margin-block-start: var(--wp--preset--spacing--60);margin-block-end: 0;}.is-layout-constrained > :first-child{margin-block-start: 0;}.is-layout-constrained > :last-child{margin-block-end: 0;}.is-layout-constrained > *{margin-block-start: var(--wp--preset--spacing--60);margin-block-end: 0;}.is-layout-flex {gap: var(--wp--preset--spacing--60);}.is-layout-grid {gap: var(--wp--preset--spacing--60);}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){max-width: var(--wp--style--global--content-size);margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignwide{max-width: var(--wp--style--global--wide-size);}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}', $theme_json->get_stylesheet( array( 'styles' ) ) ); } @@ -1345,8 +1345,8 @@ public function test_get_stylesheet_generates_valid_block_gap_values_and_skips_n ); $this->assertSame( - ':root { --wp--style--global--content-size: 640px;--wp--style--global--wide-size: 1200px; }:where(body) { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.wp-site-blocks) > * { margin-block-start: 1rem; margin-block-end: 0; }:where(.wp-site-blocks) > :first-child { margin-block-start: 0; }:where(.wp-site-blocks) > :last-child { margin-block-end: 0; }:root { --wp--style--block-gap: 1rem; }:where(.is-layout-flow) > :first-child{margin-block-start: 0;}:where(.is-layout-flow) > :last-child{margin-block-end: 0;}:where(.is-layout-flow) > *{margin-block-start: 1rem;margin-block-end: 0;}:where(.is-layout-constrained) > :first-child{margin-block-start: 0;}:where(.is-layout-constrained) > :last-child{margin-block-end: 0;}:where(.is-layout-constrained) > *{margin-block-start: 1rem;margin-block-end: 0;}:where(.is-layout-flex) {gap: 1rem;}:where(.is-layout-grid) {gap: 1rem;}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){max-width: var(--wp--style--global--content-size);margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignwide{max-width: var(--wp--style--global--wide-size);}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}' . - ':where(.wp-block-post-content){color: gray;}:where(.wp-block-social-links-is-layout-flow) > :first-child{margin-block-start: 0;}:where(.wp-block-social-links-is-layout-flow) > :last-child{margin-block-end: 0;}:where(.wp-block-social-links-is-layout-flow) > *{margin-block-start: 0;margin-block-end: 0;}:where(.wp-block-social-links-is-layout-constrained) > :first-child{margin-block-start: 0;}:where(.wp-block-social-links-is-layout-constrained) > :last-child{margin-block-end: 0;}:where(.wp-block-social-links-is-layout-constrained) > *{margin-block-start: 0;margin-block-end: 0;}:where(.wp-block-social-links-is-layout-flex) {gap: 0;}:where(.wp-block-social-links-is-layout-grid) {gap: 0;}:where(.wp-block-buttons-is-layout-flow) > :first-child{margin-block-start: 0;}:where(.wp-block-buttons-is-layout-flow) > :last-child{margin-block-end: 0;}:where(.wp-block-buttons-is-layout-flow) > *{margin-block-start: 0;margin-block-end: 0;}:where(.wp-block-buttons-is-layout-constrained) > :first-child{margin-block-start: 0;}:where(.wp-block-buttons-is-layout-constrained) > :last-child{margin-block-end: 0;}:where(.wp-block-buttons-is-layout-constrained) > *{margin-block-start: 0;margin-block-end: 0;}:where(.wp-block-buttons-is-layout-flex) {gap: 0;}:where(.wp-block-buttons-is-layout-grid) {gap: 0;}', + ':root { --wp--style--global--content-size: 640px;--wp--style--global--wide-size: 1200px; }:where(body) { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.wp-site-blocks) > * { margin-block-start: 1rem; margin-block-end: 0; }:where(.wp-site-blocks) > :first-child { margin-block-start: 0; }:where(.wp-site-blocks) > :last-child { margin-block-end: 0; }:root { --wp--style--block-gap: 1rem; }.is-layout-flow > :first-child{margin-block-start: 0;}.is-layout-flow > :last-child{margin-block-end: 0;}.is-layout-flow > *{margin-block-start: 1rem;margin-block-end: 0;}.is-layout-constrained > :first-child{margin-block-start: 0;}.is-layout-constrained > :last-child{margin-block-end: 0;}.is-layout-constrained > *{margin-block-start: 1rem;margin-block-end: 0;}.is-layout-flex {gap: 1rem;}.is-layout-grid {gap: 1rem;}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){max-width: var(--wp--style--global--content-size);margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignwide{max-width: var(--wp--style--global--wide-size);}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}' . + ':root :where(.wp-block-post-content){color: gray;}.wp-block-social-links-is-layout-flow > :first-child{margin-block-start: 0;}.wp-block-social-links-is-layout-flow > :last-child{margin-block-end: 0;}.wp-block-social-links-is-layout-flow > *{margin-block-start: 0;margin-block-end: 0;}.wp-block-social-links-is-layout-constrained > :first-child{margin-block-start: 0;}.wp-block-social-links-is-layout-constrained > :last-child{margin-block-end: 0;}.wp-block-social-links-is-layout-constrained > *{margin-block-start: 0;margin-block-end: 0;}.wp-block-social-links-is-layout-flex {gap: 0;}.wp-block-social-links-is-layout-grid {gap: 0;}.wp-block-buttons-is-layout-flow > :first-child{margin-block-start: 0;}.wp-block-buttons-is-layout-flow > :last-child{margin-block-end: 0;}.wp-block-buttons-is-layout-flow > *{margin-block-start: 0;margin-block-end: 0;}.wp-block-buttons-is-layout-constrained > :first-child{margin-block-start: 0;}.wp-block-buttons-is-layout-constrained > :last-child{margin-block-end: 0;}.wp-block-buttons-is-layout-constrained > *{margin-block-start: 0;margin-block-end: 0;}.wp-block-buttons-is-layout-flex {gap: 0;}.wp-block-buttons-is-layout-grid {gap: 0;}', $theme_json->get_stylesheet() ); } @@ -1378,7 +1378,7 @@ public function test_get_stylesheet_returns_outline_styles() { ) ); - $element_styles = ':where(.wp-element-button, .wp-block-button__link){outline-color: red;outline-offset: 3px;outline-style: dashed;outline-width: 3px;}:where(.wp-element-button:hover, .wp-block-button__link:hover){outline-color: blue;outline-offset: 3px;outline-style: solid;outline-width: 3px;}'; + $element_styles = ':root :where(.wp-element-button, .wp-block-button__link){outline-color: red;outline-offset: 3px;outline-style: dashed;outline-width: 3px;}:root :where(.wp-element-button:hover, .wp-block-button__link:hover){outline-color: blue;outline-offset: 3px;outline-style: solid;outline-width: 3px;}'; $expected = static::$base_styles . $element_styles; $this->assertSame( $expected, $theme_json->get_stylesheet() ); @@ -1403,7 +1403,7 @@ public function test_get_stylesheet_custom_root_selector() { // Results also include root site blocks styles which hard code // `:where(body) { margin: 0; }`. $this->assertSame( - ':where(body) { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.custom){color: teal;}', + ':where(body) { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:root :where(.custom){color: teal;}', $actual ); } @@ -1462,7 +1462,7 @@ public function test_get_stylesheet_generates_fluid_typography_values() { // Results also include root site blocks styles. $this->assertSame( - ':root{--wp--preset--font-size--pickles: clamp(14px, 0.875rem + ((1vw - 3.2px) * 0.156), 16px);--wp--preset--font-size--toast: clamp(14.642px, 0.915rem + ((1vw - 3.2px) * 0.575), 22px);}:where(body) { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.is-layout-flex){gap: 0.5em;}:where(.is-layout-grid){gap: 0.5em;}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){margin-left: auto !important;margin-right: auto !important;}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}:where(body){font-size: clamp(0.875em, 0.875rem + ((1vw - 0.2em) * 0.156), 1em);}:where(h1){font-size: clamp(50.171px, 3.136rem + ((1vw - 3.2px) * 3.893), 100px);}:where(.wp-block-test-clamp-me){font-size: clamp(27.894px, 1.743rem + ((1vw - 3.2px) * 1.571), 48px);}.has-pickles-font-size{font-size: var(--wp--preset--font-size--pickles) !important;}.has-toast-font-size{font-size: var(--wp--preset--font-size--toast) !important;}', + ':root{--wp--preset--font-size--pickles: clamp(14px, 0.875rem + ((1vw - 3.2px) * 0.156), 16px);--wp--preset--font-size--toast: clamp(14.642px, 0.915rem + ((1vw - 3.2px) * 0.575), 22px);}:where(body) { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.is-layout-flex){gap: 0.5em;}:where(.is-layout-grid){gap: 0.5em;}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){margin-left: auto !important;margin-right: auto !important;}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}:root :where(body){font-size: clamp(0.875em, 0.875rem + ((1vw - 0.2em) * 0.156), 1em);}:root :where(h1){font-size: clamp(50.171px, 3.136rem + ((1vw - 3.2px) * 3.893), 100px);}:root :where(.wp-block-test-clamp-me){font-size: clamp(27.894px, 1.743rem + ((1vw - 3.2px) * 1.571), 48px);}.has-pickles-font-size{font-size: var(--wp--preset--font-size--pickles) !important;}.has-toast-font-size{font-size: var(--wp--preset--font-size--toast) !important;}', $theme_json->get_stylesheet() ); } @@ -3519,7 +3519,7 @@ public function test_get_property_value_valid() { ) ); - $color_styles = ':where(body){background-color: #ffffff;color: #000000;}:where(.wp-element-button, .wp-block-button__link){background-color: #000000;color: #ffffff;}'; + $color_styles = ':root :where(body){background-color: #ffffff;color: #000000;}:root :where(.wp-element-button, .wp-block-button__link){background-color: #000000;color: #ffffff;}'; $expected = static::$base_styles . $color_styles; $this->assertSame( $expected, $theme_json->get_stylesheet() ); } @@ -3597,7 +3597,7 @@ public function test_get_property_value_loop() { ) ); - $color_styles = ':where(body){background-color: #ffffff;}:where(.wp-element-button, .wp-block-button__link){color: #ffffff;}'; + $color_styles = ':root :where(body){background-color: #ffffff;}:root :where(.wp-element-button, .wp-block-button__link){color: #ffffff;}'; $expected = static::$base_styles . $color_styles; $this->assertSame( $expected, $theme_json->get_stylesheet() ); } @@ -3630,7 +3630,7 @@ public function test_get_property_value_recursion() { ) ); - $color_styles = ':where(body){background-color: #ffffff;color: #ffffff;}:where(.wp-element-button, .wp-block-button__link){color: #ffffff;}'; + $color_styles = ':root :where(body){background-color: #ffffff;color: #ffffff;}:root :where(.wp-element-button, .wp-block-button__link){color: #ffffff;}'; $expected = static::$base_styles . $color_styles; $this->assertSame( $expected, $theme_json->get_stylesheet() ); } @@ -3654,7 +3654,7 @@ public function test_get_property_value_self() { ) ); - $color_styles = ':where(body){background-color: #ffffff;}'; + $color_styles = ':root :where(body){background-color: #ffffff;}'; $expected = static::$base_styles . $color_styles; $this->assertSame( $expected, $theme_json->get_stylesheet() ); } @@ -3684,7 +3684,7 @@ public function test_get_styles_for_block_with_padding_aware_alignments() { 'selector' => 'body', ); - $expected = ':where(body) { margin: 0; }.wp-site-blocks { padding-top: var(--wp--style--root--padding-top); padding-bottom: var(--wp--style--root--padding-bottom); }.has-global-padding { padding-right: var(--wp--style--root--padding-right); padding-left: var(--wp--style--root--padding-left); }.has-global-padding :where(.has-global-padding:not(.wp-block-block)) { padding-right: 0; padding-left: 0; }.has-global-padding > .alignfull { margin-right: calc(var(--wp--style--root--padding-right) * -1); margin-left: calc(var(--wp--style--root--padding-left) * -1); }.has-global-padding :where(.has-global-padding:not(.wp-block-block)) > .alignfull { margin-right: 0; margin-left: 0; }.has-global-padding > .alignfull:where(:not(.has-global-padding):not(.is-layout-flex):not(.is-layout-grid)) > :where([class*="wp-block-"]:not(.alignfull):not([class*="__"]),.wp-block:not(.alignfull),p,h1,h2,h3,h4,h5,h6,ul,ol) { padding-right: var(--wp--style--root--padding-right); padding-left: var(--wp--style--root--padding-left); }.has-global-padding :where(.has-global-padding) > .alignfull:where(:not(.has-global-padding)) > :where([class*="wp-block-"]:not(.alignfull):not([class*="__"]),.wp-block:not(.alignfull),p,h1,h2,h3,h4,h5,h6,ul,ol) { padding-right: 0; padding-left: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.is-layout-flex){gap: 0.5em;}:where(.is-layout-grid){gap: 0.5em;}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){margin-left: auto !important;margin-right: auto !important;}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}:where(body){--wp--style--root--padding-top: 10px;--wp--style--root--padding-right: 12px;--wp--style--root--padding-bottom: 10px;--wp--style--root--padding-left: 12px;}'; + $expected = ':where(body) { margin: 0; }.wp-site-blocks { padding-top: var(--wp--style--root--padding-top); padding-bottom: var(--wp--style--root--padding-bottom); }.has-global-padding { padding-right: var(--wp--style--root--padding-right); padding-left: var(--wp--style--root--padding-left); }.has-global-padding :where(.has-global-padding:not(.wp-block-block)) { padding-right: 0; padding-left: 0; }.has-global-padding > .alignfull { margin-right: calc(var(--wp--style--root--padding-right) * -1); margin-left: calc(var(--wp--style--root--padding-left) * -1); }.has-global-padding :where(.has-global-padding:not(.wp-block-block)) > .alignfull { margin-right: 0; margin-left: 0; }.has-global-padding > .alignfull:where(:not(.has-global-padding):not(.is-layout-flex):not(.is-layout-grid)) > :where([class*="wp-block-"]:not(.alignfull):not([class*="__"]),.wp-block:not(.alignfull),p,h1,h2,h3,h4,h5,h6,ul,ol) { padding-right: var(--wp--style--root--padding-right); padding-left: var(--wp--style--root--padding-left); }.has-global-padding :where(.has-global-padding) > .alignfull:where(:not(.has-global-padding)) > :where([class*="wp-block-"]:not(.alignfull):not([class*="__"]),.wp-block:not(.alignfull),p,h1,h2,h3,h4,h5,h6,ul,ol) { padding-right: 0; padding-left: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.is-layout-flex){gap: 0.5em;}:where(.is-layout-grid){gap: 0.5em;}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){margin-left: auto !important;margin-right: auto !important;}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}:root :where(body){--wp--style--root--padding-top: 10px;--wp--style--root--padding-right: 12px;--wp--style--root--padding-bottom: 10px;--wp--style--root--padding-left: 12px;}'; $root_rules = $theme_json->get_root_layout_rules( WP_Theme_JSON_Gutenberg::ROOT_BLOCK_SELECTOR, $metadata ); $style_rules = $theme_json->get_styles_for_block( $metadata ); $this->assertSame( $expected, $root_rules . $style_rules ); @@ -3712,7 +3712,7 @@ public function test_get_styles_for_block_without_padding_aware_alignments() { 'selector' => 'body', ); - $expected = static::$base_styles . ':where(body){padding-top: 10px;padding-right: 12px;padding-bottom: 10px;padding-left: 12px;}'; + $expected = static::$base_styles . ':root :where(body){padding-top: 10px;padding-right: 12px;padding-bottom: 10px;padding-left: 12px;}'; $root_rules = $theme_json->get_root_layout_rules( WP_Theme_JSON_Gutenberg::ROOT_BLOCK_SELECTOR, $metadata ); $style_rules = $theme_json->get_styles_for_block( $metadata ); $this->assertSame( $expected, $root_rules . $style_rules ); @@ -3757,7 +3757,7 @@ public function test_get_styles_with_appearance_tools() { 'selector' => 'body', ); - $expected = ':where(body) { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.wp-site-blocks) > * { margin-block-start: ; margin-block-end: 0; }:where(.wp-site-blocks) > :first-child { margin-block-start: 0; }:where(.wp-site-blocks) > :last-child { margin-block-end: 0; }:root { --wp--style--block-gap: ; }:where(.is-layout-flow) > :first-child{margin-block-start: 0;}:where(.is-layout-flow) > :last-child{margin-block-end: 0;}:where(.is-layout-flow) > *{margin-block-start: 1;margin-block-end: 0;}:where(.is-layout-constrained) > :first-child{margin-block-start: 0;}:where(.is-layout-constrained) > :last-child{margin-block-end: 0;}:where(.is-layout-constrained) > *{margin-block-start: 1;margin-block-end: 0;}:where(.is-layout-flex) {gap: 1;}:where(.is-layout-grid) {gap: 1;}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){margin-left: auto !important;margin-right: auto !important;}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}'; + $expected = ':where(body) { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.wp-site-blocks) > * { margin-block-start: ; margin-block-end: 0; }:where(.wp-site-blocks) > :first-child { margin-block-start: 0; }:where(.wp-site-blocks) > :last-child { margin-block-end: 0; }:root { --wp--style--block-gap: ; }.is-layout-flow > :first-child{margin-block-start: 0;}.is-layout-flow > :last-child{margin-block-end: 0;}.is-layout-flow > *{margin-block-start: 1;margin-block-end: 0;}.is-layout-constrained > :first-child{margin-block-start: 0;}.is-layout-constrained > :last-child{margin-block-end: 0;}.is-layout-constrained > *{margin-block-start: 1;margin-block-end: 0;}.is-layout-flex {gap: 1;}.is-layout-grid {gap: 1;}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){margin-left: auto !important;margin-right: auto !important;}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}'; $root_rules = $theme_json->get_root_layout_rules( WP_Theme_JSON_Gutenberg::ROOT_BLOCK_SELECTOR, $metadata ); $this->assertSame( $expected, $root_rules ); } @@ -4146,9 +4146,9 @@ public function data_get_styles_for_block_with_style_variations() { $plain = array( 'metadata' => array( 'path' => array( 'styles', 'blocks', 'core/quote', 'variations', 'plain' ), - 'selector' => '.is-style-plain.is-style-plain.wp-block-quote', + 'selector' => '.is-style-plain.wp-block-quote', ), - 'styles' => '.is-style-plain.is-style-plain.wp-block-quote{background-color: hotpink;}', + 'styles' => ':root :where(.is-style-plain.wp-block-quote){background-color: hotpink;}', ); return array( @@ -4682,7 +4682,7 @@ public function data_update_separator_declarations() { 'background' => 'blue', ), ), - 'expected_output' => static::$base_styles . ':where(.wp-block-separator){background-color: blue;color: blue;}', + 'expected_output' => static::$base_styles . ':root :where(.wp-block-separator){background-color: blue;color: blue;}', ), // If background and text are defined, do not include border-color, as text color is enough. 'background and text, no border-color' => array( @@ -4692,7 +4692,7 @@ public function data_update_separator_declarations() { 'text' => 'red', ), ), - 'expected_output' => static::$base_styles . ':where(.wp-block-separator){background-color: blue;color: red;}', + 'expected_output' => static::$base_styles . ':root :where(.wp-block-separator){background-color: blue;color: red;}', ), // If only text is defined, do not include border-color, as by itself is enough. 'only text' => array( @@ -4701,7 +4701,7 @@ public function data_update_separator_declarations() { 'text' => 'red', ), ), - 'expected_output' => static::$base_styles . ':where(.wp-block-separator){color: red;}', + 'expected_output' => static::$base_styles . ':root :where(.wp-block-separator){color: red;}', ), // If background, text, and border-color are defined, include everything, CSS specificity will decide which to apply. 'background, text, and border-color' => array( @@ -4714,7 +4714,7 @@ public function data_update_separator_declarations() { 'color' => 'pink', ), ), - 'expected_output' => static::$base_styles . ':where(.wp-block-separator){background-color: blue;border-color: pink;color: red;}', + 'expected_output' => static::$base_styles . ':root :where(.wp-block-separator){background-color: blue;border-color: pink;color: red;}', ), // If background and border color are defined, include everything, CSS specificity will decide which to apply. 'background, and border-color' => array( @@ -4726,7 +4726,7 @@ public function data_update_separator_declarations() { 'color' => 'pink', ), ), - 'expected_output' => static::$base_styles . ':where(.wp-block-separator){background-color: blue;border-color: pink;}', + 'expected_output' => static::$base_styles . ':root :where(.wp-block-separator){background-color: blue;border-color: pink;}', ), ); } @@ -4790,7 +4790,7 @@ public function test_get_shadow_styles_for_blocks() { ); $global_styles = ':root{--wp--preset--shadow--natural: 5px 5px 0 0 black;}' . static::$base_styles; - $element_styles = ':where(a:where(:not(.wp-element-button))){box-shadow: var(--wp--preset--shadow--natural);}:where(.wp-element-button, .wp-block-button__link){box-shadow: var(--wp--preset--shadow--natural);}:where(p){box-shadow: var(--wp--preset--shadow--natural);}'; + $element_styles = ':root :where(a:where(:not(.wp-element-button))){box-shadow: var(--wp--preset--shadow--natural);}:root :where(.wp-element-button, .wp-block-button__link){box-shadow: var(--wp--preset--shadow--natural);}:root :where(p){box-shadow: var(--wp--preset--shadow--natural);}'; $expected_styles = $global_styles . $element_styles; $this->assertSame( $expected_styles, $theme_json->get_stylesheet() ); } @@ -4836,7 +4836,7 @@ public function test_get_top_level_background_image_styles() { ) ); - $expected_styles = ":where(body) { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.is-layout-flex){gap: 0.5em;}:where(.is-layout-grid){gap: 0.5em;}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){margin-left: auto !important;margin-right: auto !important;}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}html{min-height: calc(100% - var(--wp-admin--admin-bar--height, 0px));}:where(body){background-image: url('http://example.org/image.png');background-position: center center;background-repeat: no-repeat;background-size: contain;}"; + $expected_styles = ":where(body) { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.is-layout-flex){gap: 0.5em;}:where(.is-layout-grid){gap: 0.5em;}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){margin-left: auto !important;margin-right: auto !important;}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}html{min-height: calc(100% - var(--wp-admin--admin-bar--height, 0px));}:root :where(body){background-image: url('http://example.org/image.png');background-position: center center;background-repeat: no-repeat;background-size: contain;}"; $this->assertSame( $expected_styles, $theme_json->get_stylesheet(), 'Styles returned from "::get_stylesheet()" with top-level background styles type does not match expectations' ); $theme_json = new WP_Theme_JSON_Gutenberg( @@ -4853,7 +4853,7 @@ public function test_get_top_level_background_image_styles() { ) ); - $expected_styles = ":where(body) { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.is-layout-flex){gap: 0.5em;}:where(.is-layout-grid){gap: 0.5em;}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){margin-left: auto !important;margin-right: auto !important;}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}html{min-height: calc(100% - var(--wp-admin--admin-bar--height, 0px));}:where(body){background-image: url('http://example.org/image.png');background-position: center center;background-repeat: no-repeat;background-size: contain;}"; + $expected_styles = ":where(body) { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.is-layout-flex){gap: 0.5em;}:where(.is-layout-grid){gap: 0.5em;}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){margin-left: auto !important;margin-right: auto !important;}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}html{min-height: calc(100% - var(--wp-admin--admin-bar--height, 0px));}:root :where(body){background-image: url('http://example.org/image.png');background-position: center center;background-repeat: no-repeat;background-size: contain;}"; $this->assertSame( $expected_styles, $theme_json->get_stylesheet(), 'Styles returned from "::get_stylesheet()" with top-level background image as string type does not match expectations' ); } @@ -4872,7 +4872,7 @@ public function test_get_custom_css_handles_global_custom_css() { ) ); - $custom_css = 'body {color:purple;}p{color:red;}'; + $custom_css = 'body {color:purple;}:root :where(p){color:red;}'; $this->assertSame( $custom_css, $theme_json->get_custom_css() ); } @@ -4979,7 +4979,7 @@ public function data_process_blocks_custom_css() { 'selector' => '.foo', 'css' => 'color: red; margin: auto;', ), - 'expected' => '.foo{color: red; margin: auto;}', + 'expected' => ':root :where(.foo){color: red; margin: auto;}', ), // CSS with nested selectors. 'with nested selector' => array( @@ -4987,7 +4987,7 @@ public function data_process_blocks_custom_css() { 'selector' => '.foo', 'css' => 'color: red; margin: auto; &.one{color: blue;} & .two{color: green;}', ), - 'expected' => '.foo{color: red; margin: auto;}.foo.one{color: blue;}.foo .two{color: green;}', + 'expected' => ':root :where(.foo){color: red; margin: auto;}:root :where(.foo.one){color: blue;}:root :where(.foo .two){color: green;}', ), // CSS with pseudo elements. 'with pseudo elements' => array( @@ -4995,7 +4995,7 @@ public function data_process_blocks_custom_css() { 'selector' => '.foo', 'css' => 'color: red; margin: auto; &::before{color: blue;} & ::before{color: green;} &.one::before{color: yellow;} & .two::before{color: purple;}', ), - 'expected' => '.foo{color: red; margin: auto;}.foo::before{color: blue;}.foo ::before{color: green;}.foo.one::before{color: yellow;}.foo .two::before{color: purple;}', + 'expected' => ':root :where(.foo){color: red; margin: auto;}:root :where(.foo::before){color: blue;}:root :where(.foo ::before){color: green;}:root :where(.foo.one::before){color: yellow;}:root :where(.foo .two::before){color: purple;}', ), // CSS with multiple root selectors. 'with multiple root selectors' => array( @@ -5003,7 +5003,7 @@ public function data_process_blocks_custom_css() { 'selector' => '.foo, .bar', 'css' => 'color: red; margin: auto; &.one{color: blue;} & .two{color: green;} &::before{color: yellow;} & ::before{color: purple;} &.three::before{color: orange;} & .four::before{color: skyblue;}', ), - 'expected' => '.foo, .bar{color: red; margin: auto;}.foo.one, .bar.one{color: blue;}.foo .two, .bar .two{color: green;}.foo::before, .bar::before{color: yellow;}.foo ::before, .bar ::before{color: purple;}.foo.three::before, .bar.three::before{color: orange;}.foo .four::before, .bar .four::before{color: skyblue;}', + 'expected' => ':root :where(.foo, .bar){color: red; margin: auto;}:root :where(.foo.one, .bar.one){color: blue;}:root :where(.foo .two, .bar .two){color: green;}:root :where(.foo::before, .bar::before){color: yellow;}:root :where(.foo ::before, .bar ::before){color: purple;}:root :where(.foo.three::before, .bar.three::before){color: orange;}:root :where(.foo .four::before, .bar .four::before){color: skyblue;}', ), ); } diff --git a/test/e2e/specs/editor/various/styles.spec.js b/test/e2e/specs/editor/various/styles.spec.js new file mode 100644 index 00000000000000..0aa1f3007d2419 --- /dev/null +++ b/test/e2e/specs/editor/various/styles.spec.js @@ -0,0 +1,17 @@ +/** + * WordPress dependencies + */ +const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' ); + +test.describe( 'Styles', () => { + test( 'should override reset styles', async ( { admin, editor } ) => { + await admin.createNewPost( { postType: 'page' } ); + await editor.insertBlock( { name: 'core/social-links' } ); + + const block = editor.canvas.getByRole( 'document', { + name: 'Block: Social Icons', + } ); + + await expect( block ).toHaveCSS( 'padding-left', '0px' ); + } ); +} ); diff --git a/test/e2e/specs/site-editor/styles.spec.js b/test/e2e/specs/site-editor/styles.spec.js new file mode 100644 index 00000000000000..66ddf0b7faa1b5 --- /dev/null +++ b/test/e2e/specs/site-editor/styles.spec.js @@ -0,0 +1,59 @@ +/** + * WordPress dependencies + */ +const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' ); + +test.describe( 'Styles', () => { + test.beforeAll( async ( { requestUtils } ) => { + await requestUtils.activateTheme( 'twentytwentythree' ); + } ); + + test.afterAll( async ( { requestUtils } ) => { + await requestUtils.activateTheme( 'twentytwentyone' ); + } ); + + test( 'should override reset styles and library styles', async ( { + admin, + editor, + requestUtils, + page, + } ) => { + const { id } = await requestUtils.createPage( { + title: 'Social Icons', + content: ` + +`, + status: 'publish', + } ); + await admin.visitSiteEditor( { + postId: id, + postType: 'page', + canvas: 'edit', + } ); + + const block = editor.canvas.getByRole( 'document', { + name: 'Block: Social Icons', + } ); + + await expect( block ).toHaveCSS( 'padding-left', '0px' ); + + const topBar = page.getByRole( 'region', { name: 'Editor top bar' } ); + // Navigate to Styles -> Blocks -> Heading -> Typography + await topBar.getByRole( 'button', { name: 'Styles' } ).click(); + await page.getByRole( 'button', { name: 'Blocks styles' } ).click(); + await page + .getByRole( 'button', { name: 'Social Icons block styles' } ) + .click(); + + // find the second padding control + const paddingControl = page + .locator( '[aria-label="padding"]' ) + .nth( 1 ); + + // Change the padding value + await paddingControl.fill( '2' ); + + // Check the padding value + await expect( block ).toHaveCSS( 'padding-left', '35.4644px' ); + } ); +} ); From ad3094187dec15e6832c134628561a236cf0b19c Mon Sep 17 00:00:00 2001 From: Rich Tabor Date: Tue, 28 May 2024 02:43:35 -0400 Subject: [PATCH 14/15] More consistent root padding (#60715) Unlinked contributors: bridgetwes. Co-authored-by: richtabor Co-authored-by: tellthemachines Co-authored-by: SaxonF Co-authored-by: bgardner Co-authored-by: fabiankaegy Co-authored-by: mikemcalister --- backport-changelog/6.6/6656.md | 3 +++ lib/class-wp-theme-json-gutenberg.php | 12 ++++-------- .../global-styles/use-global-styles-output.js | 15 +++++---------- phpunit/class-wp-theme-json-test.php | 2 +- 4 files changed, 13 insertions(+), 19 deletions(-) create mode 100644 backport-changelog/6.6/6656.md diff --git a/backport-changelog/6.6/6656.md b/backport-changelog/6.6/6656.md new file mode 100644 index 00000000000000..f0bf8900335f49 --- /dev/null +++ b/backport-changelog/6.6/6656.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/6656 + +* https://github.com/WordPress/gutenberg/pull/60715 \ No newline at end of file diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index 75b9ef60ff1fc8..b5636ad7c8dc57 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -2818,16 +2818,12 @@ public function get_root_layout_rules( $selector, $block_metadata ) { $css .= '.wp-site-blocks { padding-top: var(--wp--style--root--padding-top); padding-bottom: var(--wp--style--root--padding-bottom); }'; // Right and left padding are applied to the first container with `.has-global-padding` class. $css .= '.has-global-padding { padding-right: var(--wp--style--root--padding-right); padding-left: var(--wp--style--root--padding-left); }'; - // Nested containers with `.has-global-padding` class do not get padding. - $css .= '.has-global-padding :where(.has-global-padding:not(.wp-block-block)) { padding-right: 0; padding-left: 0; }'; // Alignfull children of the container with left and right padding have negative margins so they can still be full width. $css .= '.has-global-padding > .alignfull { margin-right: calc(var(--wp--style--root--padding-right) * -1); margin-left: calc(var(--wp--style--root--padding-left) * -1); }'; - // The above rule is negated for alignfull children of nested containers. - $css .= '.has-global-padding :where(.has-global-padding:not(.wp-block-block)) > .alignfull { margin-right: 0; margin-left: 0; }'; - // Some of the children of alignfull blocks without content width should also get padding: text blocks and non-alignfull container blocks. - $css .= '.has-global-padding > .alignfull:where(:not(.has-global-padding):not(.is-layout-flex):not(.is-layout-grid)) > :where([class*="wp-block-"]:not(.alignfull):not([class*="__"]),.wp-block:not(.alignfull),p,h1,h2,h3,h4,h5,h6,ul,ol) { padding-right: var(--wp--style--root--padding-right); padding-left: var(--wp--style--root--padding-left); }'; - // The above rule also has to be negated for blocks inside nested `.has-global-padding` blocks. - $css .= '.has-global-padding :where(.has-global-padding) > .alignfull:where(:not(.has-global-padding)) > :where([class*="wp-block-"]:not(.alignfull):not([class*="__"]),.wp-block:not(.alignfull),p,h1,h2,h3,h4,h5,h6,ul,ol) { padding-right: 0; padding-left: 0; }'; + // Nested children of the container with left and right padding that are not wide or full aligned do not get padding. + $css .= '.has-global-padding :where(.has-global-padding:not(.wp-block-block, .alignfull, .alignwide)) { padding-right: 0; padding-left: 0; }'; + // Nested children of the container with left and right padding that are not wide or full aligned do not get negative margin applied. + $css .= '.has-global-padding :where(.has-global-padding:not(.wp-block-block, .alignfull, .alignwide)) > .alignfull { margin-left: 0; margin-right: 0; }'; } $css .= '.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }'; diff --git a/packages/block-editor/src/components/global-styles/use-global-styles-output.js b/packages/block-editor/src/components/global-styles/use-global-styles-output.js index 06d9400416eebb..f2eaa50a890a9b 100644 --- a/packages/block-editor/src/components/global-styles/use-global-styles-output.js +++ b/packages/block-editor/src/components/global-styles/use-global-styles-output.js @@ -815,23 +815,18 @@ export const toStyles = ( */ ruleset += ':where(body) {margin: 0;'; - // Root padding styles should only be output for full templates, not patterns or template parts. - if ( - options.rootPadding && - useRootPaddingAlign && - ! disableRootPadding - ) { + // Root padding styles should be output for full templates, patterns and template parts. + if ( options.rootPadding && useRootPaddingAlign ) { /* * These rules reproduce the ones from https://github.com/WordPress/gutenberg/blob/79103f124925d1f457f627e154f52a56228ed5ad/lib/class-wp-theme-json-gutenberg.php#L2508 * almost exactly, but for the selectors that target block wrappers in the front end. This code only runs in the editor, so it doesn't need those selectors. */ ruleset += `padding-right: 0; padding-left: 0; padding-top: var(--wp--style--root--padding-top); padding-bottom: var(--wp--style--root--padding-bottom) } .has-global-padding { padding-right: var(--wp--style--root--padding-right); padding-left: var(--wp--style--root--padding-left); } - .has-global-padding :where(.has-global-padding:not(.wp-block-block)) { padding-right: 0; padding-left: 0; } .has-global-padding > .alignfull { margin-right: calc(var(--wp--style--root--padding-right) * -1); margin-left: calc(var(--wp--style--root--padding-left) * -1); } - .has-global-padding :where(.has-global-padding:not(.wp-block-block)) > .alignfull { margin-right: 0; margin-left: 0; } - .has-global-padding > .alignfull:where(:not(.has-global-padding):not(.is-layout-flex):not(.is-layout-grid)) > :where(.wp-block:not(.alignfull),p,h1,h2,h3,h4,h5,h6,ul,ol) { padding-right: var(--wp--style--root--padding-right); padding-left: var(--wp--style--root--padding-left); } - .has-global-padding :where(.has-global-padding) > .alignfull:where(:not(.has-global-padding)) > :where(.wp-block:not(.alignfull),p,h1,h2,h3,h4,h5,h6,ul,ol) { padding-right: 0; padding-left: 0;`; + .has-global-padding :where(.has-global-padding:not(.wp-block-block, .alignfull, .alignwide)) { padding-right: 0; padding-left: 0; } + .has-global-padding :where(.has-global-padding:not(.wp-block-block, .alignfull, .alignwide)) > .alignfull { margin-left: 0; margin-right: 0; } + `; } ruleset += '}'; diff --git a/phpunit/class-wp-theme-json-test.php b/phpunit/class-wp-theme-json-test.php index aed3e9963ac25b..28401bb20d484d 100644 --- a/phpunit/class-wp-theme-json-test.php +++ b/phpunit/class-wp-theme-json-test.php @@ -3684,7 +3684,7 @@ public function test_get_styles_for_block_with_padding_aware_alignments() { 'selector' => 'body', ); - $expected = ':where(body) { margin: 0; }.wp-site-blocks { padding-top: var(--wp--style--root--padding-top); padding-bottom: var(--wp--style--root--padding-bottom); }.has-global-padding { padding-right: var(--wp--style--root--padding-right); padding-left: var(--wp--style--root--padding-left); }.has-global-padding :where(.has-global-padding:not(.wp-block-block)) { padding-right: 0; padding-left: 0; }.has-global-padding > .alignfull { margin-right: calc(var(--wp--style--root--padding-right) * -1); margin-left: calc(var(--wp--style--root--padding-left) * -1); }.has-global-padding :where(.has-global-padding:not(.wp-block-block)) > .alignfull { margin-right: 0; margin-left: 0; }.has-global-padding > .alignfull:where(:not(.has-global-padding):not(.is-layout-flex):not(.is-layout-grid)) > :where([class*="wp-block-"]:not(.alignfull):not([class*="__"]),.wp-block:not(.alignfull),p,h1,h2,h3,h4,h5,h6,ul,ol) { padding-right: var(--wp--style--root--padding-right); padding-left: var(--wp--style--root--padding-left); }.has-global-padding :where(.has-global-padding) > .alignfull:where(:not(.has-global-padding)) > :where([class*="wp-block-"]:not(.alignfull):not([class*="__"]),.wp-block:not(.alignfull),p,h1,h2,h3,h4,h5,h6,ul,ol) { padding-right: 0; padding-left: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.is-layout-flex){gap: 0.5em;}:where(.is-layout-grid){gap: 0.5em;}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){margin-left: auto !important;margin-right: auto !important;}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}:root :where(body){--wp--style--root--padding-top: 10px;--wp--style--root--padding-right: 12px;--wp--style--root--padding-bottom: 10px;--wp--style--root--padding-left: 12px;}'; + $expected = ':where(body) { margin: 0; }.wp-site-blocks { padding-top: var(--wp--style--root--padding-top); padding-bottom: var(--wp--style--root--padding-bottom); }.has-global-padding { padding-right: var(--wp--style--root--padding-right); padding-left: var(--wp--style--root--padding-left); }.has-global-padding > .alignfull { margin-right: calc(var(--wp--style--root--padding-right) * -1); margin-left: calc(var(--wp--style--root--padding-left) * -1); }.has-global-padding :where(.has-global-padding:not(.wp-block-block, .alignfull, .alignwide)) { padding-right: 0; padding-left: 0; }.has-global-padding :where(.has-global-padding:not(.wp-block-block, .alignfull, .alignwide)) > .alignfull { margin-left: 0; margin-right: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.is-layout-flex){gap: 0.5em;}:where(.is-layout-grid){gap: 0.5em;}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){margin-left: auto !important;margin-right: auto !important;}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}:root :where(body){--wp--style--root--padding-top: 10px;--wp--style--root--padding-right: 12px;--wp--style--root--padding-bottom: 10px;--wp--style--root--padding-left: 12px;}'; $root_rules = $theme_json->get_root_layout_rules( WP_Theme_JSON_Gutenberg::ROOT_BLOCK_SELECTOR, $metadata ); $style_rules = $theme_json->get_styles_for_block( $metadata ); $this->assertSame( $expected, $root_rules . $style_rules ); From 513f9eae653f0e4e4e854c52ca2ea00c6e959ba4 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Tue, 28 May 2024 09:06:36 +0100 Subject: [PATCH 15/15] BlockLibrary: Remove useless styles (#62017) Co-authored-by: youknowriad Co-authored-by: jasmussen --- packages/block-library/src/block/editor.scss | 35 ------------------- packages/block-library/src/editor.scss | 1 - .../src/latest-posts/editor.scss | 4 --- 3 files changed, 40 deletions(-) delete mode 100644 packages/block-library/src/block/editor.scss diff --git a/packages/block-library/src/block/editor.scss b/packages/block-library/src/block/editor.scss deleted file mode 100644 index 318101f7f52dac..00000000000000 --- a/packages/block-library/src/block/editor.scss +++ /dev/null @@ -1,35 +0,0 @@ -.edit-post-visual-editor .block-library-block__reusable-block-container { - // Unset the padding that root containers get when they're actually root containers. - .is-root-container { - padding-left: 0; - padding-right: 0; - } - - // Allow vertical paddings to collapse to better fit the flow. - .block-editor-writing-flow { - display: block; - } - - .components-disabled .block-list-appender { - display: none; - } -} - -.edit-post-visual-editor .block-editor-block-list__block:not(.remove-outline).is-reusable { - - &.is-highlighted::after, - &.is-selected::after { - outline-color: var(--wp-block-synced-color); - } - - &.block-editor-block-list__block:not([contenteditable]):focus { - &::after { - outline-color: var(--wp-block-synced-color); - - // Show a light color for dark themes. - .is-dark-theme & { - outline-color: $dark-theme-focus; - } - } - } -} diff --git a/packages/block-library/src/editor.scss b/packages/block-library/src/editor.scss index 0bca3e23028c50..c43137c632b73f 100644 --- a/packages/block-library/src/editor.scss +++ b/packages/block-library/src/editor.scss @@ -1,7 +1,6 @@ @import "./archives/editor.scss"; @import "./audio/editor.scss"; @import "./avatar/editor.scss"; -@import "./block/editor.scss"; @import "./button/editor.scss"; @import "./buttons/editor.scss"; @import "./categories/editor.scss"; diff --git a/packages/block-library/src/latest-posts/editor.scss b/packages/block-library/src/latest-posts/editor.scss index a963ab531597c6..d3f0b5275653e3 100644 --- a/packages/block-library/src/latest-posts/editor.scss +++ b/packages/block-library/src/latest-posts/editor.scss @@ -9,10 +9,6 @@ display: inline; } -.edit-post-visual-editor .wp-block-latest-posts.is-grid li { - margin-bottom: 20px; -} - .editor-latest-posts-image-alignment-control { .components-base-control__label { display: block;