diff --git a/packages/server-side-render/CHANGELOG.md b/packages/server-side-render/CHANGELOG.md index 9be8f2b185cdb..b8398f158dddf 100644 --- a/packages/server-side-render/CHANGELOG.md +++ b/packages/server-side-render/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Feature + +- Add `skipBlockSupportAttributes` props to prevent duplication of styles in the block wrapper and the `ServerSideRender` components. [#44491](https://github.com/WordPress/gutenberg/pull/44491) + ## 3.17.0 (2022-10-05) ## 3.16.0 (2022-09-21) diff --git a/packages/server-side-render/README.md b/packages/server-side-render/README.md index 55dc97ec09134..9c78086893147 100644 --- a/packages/server-side-render/README.md +++ b/packages/server-side-render/README.md @@ -56,6 +56,7 @@ The HTTP request method to use, either 'GET' or 'POST'. It's 'GET' by default. T - Type: `String` - Required: No +- Default: 'GET' #### Example: @@ -76,6 +77,14 @@ function add_rest_method( $endpoints ) { add_filter( 'rest_endpoints', 'add_rest_method'); ``` +### skipBlockSupportAttributes + +Remove attributes and style properties applied by the block supports. This prevents duplication of styles in the block wrapper and the `ServerSideRender` components. Even if certain features skip serialization to HTML markup by `__experimentalSkipSerialization`, all attributes and style properties are removed. + +- Type: `Boolean` +- Required: No +- Default: false + ### urlQueryArgs Query arguments to apply to the request URL. diff --git a/packages/server-side-render/src/server-side-render.js b/packages/server-side-render/src/server-side-render.js index deb7d025b647e..07d120e11440d 100644 --- a/packages/server-side-render/src/server-side-render.js +++ b/packages/server-side-render/src/server-side-render.js @@ -14,6 +14,8 @@ import { addQueryArgs } from '@wordpress/url'; import { Placeholder, Spinner } from '@wordpress/components'; import { __experimentalSanitizeBlockAttributes } from '@wordpress/blocks'; +const EMPTY_OBJECT = {}; + export function rendererPath( block, attributes = null, urlQueryArgs = {} ) { return addQueryArgs( `/wp/v2/block-renderer/${ block }`, { context: 'edit', @@ -22,6 +24,27 @@ export function rendererPath( block, attributes = null, urlQueryArgs = {} ) { } ); } +export function removeBlockSupportAttributes( attributes ) { + const { + backgroundColor, + borderColor, + fontFamily, + fontSize, + gradient, + textColor, + className, + ...restAttributes + } = attributes; + + const { border, color, elements, spacing, typography, ...restStyles } = + attributes?.style || EMPTY_OBJECT; + + return { + ...restAttributes, + style: restStyles, + }; +} + function DefaultEmptyResponsePlaceholder( { className } ) { return ( @@ -69,6 +92,7 @@ export default function ServerSideRender( props ) { className, httpMethod = 'GET', urlQueryArgs, + skipBlockSupportAttributes = false, EmptyResponsePlaceholder = DefaultEmptyResponsePlaceholder, ErrorResponsePlaceholder = DefaultErrorResponsePlaceholder, LoadingResponsePlaceholder = DefaultLoadingResponsePlaceholder, @@ -88,10 +112,15 @@ export default function ServerSideRender( props ) { setIsLoading( true ); - const sanitizedAttributes = + let sanitizedAttributes = attributes && __experimentalSanitizeBlockAttributes( block, attributes ); + if ( skipBlockSupportAttributes ) { + sanitizedAttributes = + removeBlockSupportAttributes( sanitizedAttributes ); + } + // If httpMethod is 'POST', send the attributes in the request body instead of the URL. // This allows sending a larger attributes object than in a GET request, where the attributes are in the URL. const isPostRequest = 'POST' === httpMethod; diff --git a/packages/server-side-render/src/test/index.js b/packages/server-side-render/src/test/index.js index 60b2f89007ade..13819fedd3c2b 100644 --- a/packages/server-side-render/src/test/index.js +++ b/packages/server-side-render/src/test/index.js @@ -1,7 +1,10 @@ /** * Internal dependencies */ -import { rendererPath } from '../server-side-render'; +import { + rendererPath, + removeBlockSupportAttributes, +} from '../server-side-render'; describe( 'rendererPath', () => { test( 'should return an base path for empty input', () => { @@ -75,4 +78,66 @@ describe( 'rendererPath', () => { '/wp/v2/block-renderer/core/test-block?context=edit&attributes%5BstringArg%5D=test&id=1234' ); } ); + + test( 'Should remove attributes and style properties applied by the block supports', () => { + expect( + removeBlockSupportAttributes( { + backgroundColor: 'foreground', + borderColor: 'foreground', + fontFamily: 'system-font', + fontSize: 'small', + gradient: 'vivid-cyan-blue-to-vivid-purple', + textColor: 'foreground', + customAttribute: 'customAttribute', + className: 'custom-class', + style: { + border: { + radius: '10px', + style: 'solid', + width: '10px', + }, + color: { + background: '#000000', + text: '#000000', + }, + elements: { + link: { + color: { + text: '#000000', + }, + }, + }, + spacing: { + margin: { + top: '10px', + right: '10px', + bottom: '10px', + left: '10px', + }, + padding: { + top: '10px', + right: '10px', + bottom: '10px', + left: '10px', + }, + }, + typography: { + fontSize: '10px', + fontStyle: 'normal', + fontWeight: '500', + letterSpacing: '10px', + lineHeight: '1', + textDecoration: 'line-through', + textTransform: 'uppercase', + }, + customStyle: 'customStyle', + }, + } ) + ).toEqual( { + customAttribute: 'customAttribute', + style: { + customStyle: 'customStyle', + }, + } ); + } ); } );