@wordpress/server-side-render 3.16.1-next.4d3b314fd5.0 → 3.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,14 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 3.18.0 (2022-10-19)
6
+
7
+ ### Feature
8
+
9
+ - Add `skipBlockSupportAttributes` props to prevent duplication of styles in the block wrapper and the `ServerSideRender` components. [#44491](https://github.com/WordPress/gutenberg/pull/44491)
10
+
11
+ ## 3.17.0 (2022-10-05)
12
+
5
13
  ## 3.16.0 (2022-09-21)
6
14
 
7
15
  ## 3.15.0 (2022-09-13)
package/README.md CHANGED
@@ -56,6 +56,7 @@ The HTTP request method to use, either 'GET' or 'POST'. It's 'GET' by default. T
56
56
 
57
57
  - Type: `String`
58
58
  - Required: No
59
+ - Default: 'GET'
59
60
 
60
61
  #### Example:
61
62
 
@@ -76,6 +77,14 @@ function add_rest_method( $endpoints ) {
76
77
  add_filter( 'rest_endpoints', 'add_rest_method');
77
78
  ```
78
79
 
80
+ ### skipBlockSupportAttributes
81
+
82
+ 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.
83
+
84
+ - Type: `Boolean`
85
+ - Required: No
86
+ - Default: false
87
+
79
88
  ### urlQueryArgs
80
89
 
81
90
  Query arguments to apply to the request URL.
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  value: true
7
7
  });
8
8
  exports.default = ServerSideRender;
9
+ exports.removeBlockSupportAttributes = removeBlockSupportAttributes;
9
10
  exports.rendererPath = rendererPath;
10
11
 
11
12
  var _element = require("@wordpress/element");
@@ -33,6 +34,8 @@ var _blocks = require("@wordpress/blocks");
33
34
  /**
34
35
  * WordPress dependencies
35
36
  */
37
+ const EMPTY_OBJECT = {};
38
+
36
39
  function rendererPath(block) {
37
40
  let attributes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
38
41
  let urlQueryArgs = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
@@ -45,6 +48,30 @@ function rendererPath(block) {
45
48
  });
46
49
  }
47
50
 
51
+ function removeBlockSupportAttributes(attributes) {
52
+ const {
53
+ backgroundColor,
54
+ borderColor,
55
+ fontFamily,
56
+ fontSize,
57
+ gradient,
58
+ textColor,
59
+ className,
60
+ ...restAttributes
61
+ } = attributes;
62
+ const {
63
+ border,
64
+ color,
65
+ elements,
66
+ spacing,
67
+ typography,
68
+ ...restStyles
69
+ } = (attributes === null || attributes === void 0 ? void 0 : attributes.style) || EMPTY_OBJECT;
70
+ return { ...restAttributes,
71
+ style: restStyles
72
+ };
73
+ }
74
+
48
75
  function DefaultEmptyResponsePlaceholder(_ref) {
49
76
  let {
50
77
  className
@@ -97,6 +124,7 @@ function ServerSideRender(props) {
97
124
  className,
98
125
  httpMethod = 'GET',
99
126
  urlQueryArgs,
127
+ skipBlockSupportAttributes = false,
100
128
  EmptyResponsePlaceholder = DefaultEmptyResponsePlaceholder,
101
129
  ErrorResponsePlaceholder = DefaultErrorResponsePlaceholder,
102
130
  LoadingResponsePlaceholder = DefaultLoadingResponsePlaceholder
@@ -109,19 +137,26 @@ function ServerSideRender(props) {
109
137
  const [isLoading, setIsLoading] = (0, _element.useState)(false);
110
138
 
111
139
  function fetchData() {
140
+ var _sanitizedAttributes, _sanitizedAttributes2;
141
+
112
142
  if (!isMountedRef.current) {
113
143
  return;
114
144
  }
115
145
 
116
146
  setIsLoading(true);
117
- const sanitizedAttributes = attributes && (0, _blocks.__experimentalSanitizeBlockAttributes)(block, attributes); // If httpMethod is 'POST', send the attributes in the request body instead of the URL.
147
+ let sanitizedAttributes = attributes && (0, _blocks.__experimentalSanitizeBlockAttributes)(block, attributes);
148
+
149
+ if (skipBlockSupportAttributes) {
150
+ sanitizedAttributes = removeBlockSupportAttributes(sanitizedAttributes);
151
+ } // If httpMethod is 'POST', send the attributes in the request body instead of the URL.
118
152
  // This allows sending a larger attributes object than in a GET request, where the attributes are in the URL.
119
153
 
154
+
120
155
  const isPostRequest = 'POST' === httpMethod;
121
- const urlAttributes = isPostRequest ? null : sanitizedAttributes !== null && sanitizedAttributes !== void 0 ? sanitizedAttributes : null;
156
+ const urlAttributes = isPostRequest ? null : (_sanitizedAttributes = sanitizedAttributes) !== null && _sanitizedAttributes !== void 0 ? _sanitizedAttributes : null;
122
157
  const path = rendererPath(block, urlAttributes, urlQueryArgs);
123
158
  const data = isPostRequest ? {
124
- attributes: sanitizedAttributes !== null && sanitizedAttributes !== void 0 ? sanitizedAttributes : null
159
+ attributes: (_sanitizedAttributes2 = sanitizedAttributes) !== null && _sanitizedAttributes2 !== void 0 ? _sanitizedAttributes2 : null
125
160
  } : null; // Store the latest fetch request so that when we process it, we can
126
161
  // check if it is the current request, to avoid race conditions on slow networks.
127
162
 
@@ -1 +1 @@
1
- {"version":3,"sources":["@wordpress/server-side-render/src/server-side-render.js"],"names":["rendererPath","block","attributes","urlQueryArgs","context","DefaultEmptyResponsePlaceholder","className","DefaultErrorResponsePlaceholder","response","errorMessage","errorMsg","DefaultLoadingResponsePlaceholder","children","showLoader","position","top","left","marginTop","marginLeft","opacity","ServerSideRender","props","httpMethod","EmptyResponsePlaceholder","ErrorResponsePlaceholder","LoadingResponsePlaceholder","isMountedRef","setShowLoader","fetchRequestRef","setResponse","prevProps","isLoading","setIsLoading","fetchData","current","sanitizedAttributes","isPostRequest","urlAttributes","path","data","fetchRequest","method","then","fetchResponse","rendered","catch","error","message","finally","debouncedFetchData","undefined","timeout","setTimeout","clearTimeout","hasResponse","hasEmptyResponse","hasError"],"mappings":"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","sourcesContent":["/**\n * External dependencies\n */\nimport { isEqual } from 'lodash';\n\n/**\n * WordPress dependencies\n */\nimport { useDebounce, usePrevious } from '@wordpress/compose';\nimport { RawHTML, useEffect, useRef, useState } from '@wordpress/element';\nimport { __, sprintf } from '@wordpress/i18n';\nimport apiFetch from '@wordpress/api-fetch';\nimport { addQueryArgs } from '@wordpress/url';\nimport { Placeholder, Spinner } from '@wordpress/components';\nimport { __experimentalSanitizeBlockAttributes } from '@wordpress/blocks';\n\nexport function rendererPath( block, attributes = null, urlQueryArgs = {} ) {\n\treturn addQueryArgs( `/wp/v2/block-renderer/${ block }`, {\n\t\tcontext: 'edit',\n\t\t...( null !== attributes ? { attributes } : {} ),\n\t\t...urlQueryArgs,\n\t} );\n}\n\nfunction DefaultEmptyResponsePlaceholder( { className } ) {\n\treturn (\n\t\t<Placeholder className={ className }>\n\t\t\t{ __( 'Block rendered as empty.' ) }\n\t\t</Placeholder>\n\t);\n}\n\nfunction DefaultErrorResponsePlaceholder( { response, className } ) {\n\tconst errorMessage = sprintf(\n\t\t// translators: %s: error message describing the problem\n\t\t__( 'Error loading block: %s' ),\n\t\tresponse.errorMsg\n\t);\n\treturn <Placeholder className={ className }>{ errorMessage }</Placeholder>;\n}\n\nfunction DefaultLoadingResponsePlaceholder( { children, showLoader } ) {\n\treturn (\n\t\t<div style={ { position: 'relative' } }>\n\t\t\t{ showLoader && (\n\t\t\t\t<div\n\t\t\t\t\tstyle={ {\n\t\t\t\t\t\tposition: 'absolute',\n\t\t\t\t\t\ttop: '50%',\n\t\t\t\t\t\tleft: '50%',\n\t\t\t\t\t\tmarginTop: '-9px',\n\t\t\t\t\t\tmarginLeft: '-9px',\n\t\t\t\t\t} }\n\t\t\t\t>\n\t\t\t\t\t<Spinner />\n\t\t\t\t</div>\n\t\t\t) }\n\t\t\t<div style={ { opacity: showLoader ? '0.3' : 1 } }>\n\t\t\t\t{ children }\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\nexport default function ServerSideRender( props ) {\n\tconst {\n\t\tattributes,\n\t\tblock,\n\t\tclassName,\n\t\thttpMethod = 'GET',\n\t\turlQueryArgs,\n\t\tEmptyResponsePlaceholder = DefaultEmptyResponsePlaceholder,\n\t\tErrorResponsePlaceholder = DefaultErrorResponsePlaceholder,\n\t\tLoadingResponsePlaceholder = DefaultLoadingResponsePlaceholder,\n\t} = props;\n\n\tconst isMountedRef = useRef( true );\n\tconst [ showLoader, setShowLoader ] = useState( false );\n\tconst fetchRequestRef = useRef();\n\tconst [ response, setResponse ] = useState( null );\n\tconst prevProps = usePrevious( props );\n\tconst [ isLoading, setIsLoading ] = useState( false );\n\n\tfunction fetchData() {\n\t\tif ( ! isMountedRef.current ) {\n\t\t\treturn;\n\t\t}\n\n\t\tsetIsLoading( true );\n\n\t\tconst sanitizedAttributes =\n\t\t\tattributes &&\n\t\t\t__experimentalSanitizeBlockAttributes( block, attributes );\n\n\t\t// If httpMethod is 'POST', send the attributes in the request body instead of the URL.\n\t\t// This allows sending a larger attributes object than in a GET request, where the attributes are in the URL.\n\t\tconst isPostRequest = 'POST' === httpMethod;\n\t\tconst urlAttributes = isPostRequest\n\t\t\t? null\n\t\t\t: sanitizedAttributes ?? null;\n\t\tconst path = rendererPath( block, urlAttributes, urlQueryArgs );\n\t\tconst data = isPostRequest\n\t\t\t? { attributes: sanitizedAttributes ?? null }\n\t\t\t: null;\n\n\t\t// Store the latest fetch request so that when we process it, we can\n\t\t// check if it is the current request, to avoid race conditions on slow networks.\n\t\tconst fetchRequest = ( fetchRequestRef.current = apiFetch( {\n\t\t\tpath,\n\t\t\tdata,\n\t\t\tmethod: isPostRequest ? 'POST' : 'GET',\n\t\t} )\n\t\t\t.then( ( fetchResponse ) => {\n\t\t\t\tif (\n\t\t\t\t\tisMountedRef.current &&\n\t\t\t\t\tfetchRequest === fetchRequestRef.current &&\n\t\t\t\t\tfetchResponse\n\t\t\t\t) {\n\t\t\t\t\tsetResponse( fetchResponse.rendered );\n\t\t\t\t}\n\t\t\t} )\n\t\t\t.catch( ( error ) => {\n\t\t\t\tif (\n\t\t\t\t\tisMountedRef.current &&\n\t\t\t\t\tfetchRequest === fetchRequestRef.current\n\t\t\t\t) {\n\t\t\t\t\tsetResponse( {\n\t\t\t\t\t\terror: true,\n\t\t\t\t\t\terrorMsg: error.message,\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t} )\n\t\t\t.finally( () => {\n\t\t\t\tif (\n\t\t\t\t\tisMountedRef.current &&\n\t\t\t\t\tfetchRequest === fetchRequestRef.current\n\t\t\t\t) {\n\t\t\t\t\tsetIsLoading( false );\n\t\t\t\t}\n\t\t\t} ) );\n\n\t\treturn fetchRequest;\n\t}\n\n\tconst debouncedFetchData = useDebounce( fetchData, 500 );\n\n\t// When the component unmounts, set isMountedRef to false. This will\n\t// let the async fetch callbacks know when to stop.\n\tuseEffect(\n\t\t() => () => {\n\t\t\tisMountedRef.current = false;\n\t\t},\n\t\t[]\n\t);\n\n\tuseEffect( () => {\n\t\t// Don't debounce the first fetch. This ensures that the first render\n\t\t// shows data as soon as possible.\n\t\tif ( prevProps === undefined ) {\n\t\t\tfetchData();\n\t\t} else if ( ! isEqual( prevProps, props ) ) {\n\t\t\tdebouncedFetchData();\n\t\t}\n\t} );\n\n\t/**\n\t * Effect to handle showing the loading placeholder.\n\t * Show it only if there is no previous response or\n\t * the request takes more than one second.\n\t */\n\tuseEffect( () => {\n\t\tif ( ! isLoading ) {\n\t\t\treturn;\n\t\t}\n\t\tconst timeout = setTimeout( () => {\n\t\t\tsetShowLoader( true );\n\t\t}, 1000 );\n\t\treturn () => clearTimeout( timeout );\n\t}, [ isLoading ] );\n\n\tconst hasResponse = !! response;\n\tconst hasEmptyResponse = response === '';\n\tconst hasError = response?.error;\n\n\tif ( isLoading ) {\n\t\treturn (\n\t\t\t<LoadingResponsePlaceholder { ...props } showLoader={ showLoader }>\n\t\t\t\t{ hasResponse && (\n\t\t\t\t\t<RawHTML className={ className }>{ response }</RawHTML>\n\t\t\t\t) }\n\t\t\t</LoadingResponsePlaceholder>\n\t\t);\n\t}\n\n\tif ( hasEmptyResponse || ! hasResponse ) {\n\t\treturn <EmptyResponsePlaceholder { ...props } />;\n\t}\n\n\tif ( hasError ) {\n\t\treturn <ErrorResponsePlaceholder response={ response } { ...props } />;\n\t}\n\n\treturn <RawHTML className={ className }>{ response }</RawHTML>;\n}\n"]}
1
+ {"version":3,"sources":["@wordpress/server-side-render/src/server-side-render.js"],"names":["EMPTY_OBJECT","rendererPath","block","attributes","urlQueryArgs","context","removeBlockSupportAttributes","backgroundColor","borderColor","fontFamily","fontSize","gradient","textColor","className","restAttributes","border","color","elements","spacing","typography","restStyles","style","DefaultEmptyResponsePlaceholder","DefaultErrorResponsePlaceholder","response","errorMessage","errorMsg","DefaultLoadingResponsePlaceholder","children","showLoader","position","top","left","marginTop","marginLeft","opacity","ServerSideRender","props","httpMethod","skipBlockSupportAttributes","EmptyResponsePlaceholder","ErrorResponsePlaceholder","LoadingResponsePlaceholder","isMountedRef","setShowLoader","fetchRequestRef","setResponse","prevProps","isLoading","setIsLoading","fetchData","current","sanitizedAttributes","isPostRequest","urlAttributes","path","data","fetchRequest","method","then","fetchResponse","rendered","catch","error","message","finally","debouncedFetchData","undefined","timeout","setTimeout","clearTimeout","hasResponse","hasEmptyResponse","hasError"],"mappings":"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","sourcesContent":["/**\n * External dependencies\n */\nimport { isEqual } from 'lodash';\n\n/**\n * WordPress dependencies\n */\nimport { useDebounce, usePrevious } from '@wordpress/compose';\nimport { RawHTML, useEffect, useRef, useState } from '@wordpress/element';\nimport { __, sprintf } from '@wordpress/i18n';\nimport apiFetch from '@wordpress/api-fetch';\nimport { addQueryArgs } from '@wordpress/url';\nimport { Placeholder, Spinner } from '@wordpress/components';\nimport { __experimentalSanitizeBlockAttributes } from '@wordpress/blocks';\n\nconst EMPTY_OBJECT = {};\n\nexport function rendererPath( block, attributes = null, urlQueryArgs = {} ) {\n\treturn addQueryArgs( `/wp/v2/block-renderer/${ block }`, {\n\t\tcontext: 'edit',\n\t\t...( null !== attributes ? { attributes } : {} ),\n\t\t...urlQueryArgs,\n\t} );\n}\n\nexport function removeBlockSupportAttributes( attributes ) {\n\tconst {\n\t\tbackgroundColor,\n\t\tborderColor,\n\t\tfontFamily,\n\t\tfontSize,\n\t\tgradient,\n\t\ttextColor,\n\t\tclassName,\n\t\t...restAttributes\n\t} = attributes;\n\n\tconst { border, color, elements, spacing, typography, ...restStyles } =\n\t\tattributes?.style || EMPTY_OBJECT;\n\n\treturn {\n\t\t...restAttributes,\n\t\tstyle: restStyles,\n\t};\n}\n\nfunction DefaultEmptyResponsePlaceholder( { className } ) {\n\treturn (\n\t\t<Placeholder className={ className }>\n\t\t\t{ __( 'Block rendered as empty.' ) }\n\t\t</Placeholder>\n\t);\n}\n\nfunction DefaultErrorResponsePlaceholder( { response, className } ) {\n\tconst errorMessage = sprintf(\n\t\t// translators: %s: error message describing the problem\n\t\t__( 'Error loading block: %s' ),\n\t\tresponse.errorMsg\n\t);\n\treturn <Placeholder className={ className }>{ errorMessage }</Placeholder>;\n}\n\nfunction DefaultLoadingResponsePlaceholder( { children, showLoader } ) {\n\treturn (\n\t\t<div style={ { position: 'relative' } }>\n\t\t\t{ showLoader && (\n\t\t\t\t<div\n\t\t\t\t\tstyle={ {\n\t\t\t\t\t\tposition: 'absolute',\n\t\t\t\t\t\ttop: '50%',\n\t\t\t\t\t\tleft: '50%',\n\t\t\t\t\t\tmarginTop: '-9px',\n\t\t\t\t\t\tmarginLeft: '-9px',\n\t\t\t\t\t} }\n\t\t\t\t>\n\t\t\t\t\t<Spinner />\n\t\t\t\t</div>\n\t\t\t) }\n\t\t\t<div style={ { opacity: showLoader ? '0.3' : 1 } }>\n\t\t\t\t{ children }\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\nexport default function ServerSideRender( props ) {\n\tconst {\n\t\tattributes,\n\t\tblock,\n\t\tclassName,\n\t\thttpMethod = 'GET',\n\t\turlQueryArgs,\n\t\tskipBlockSupportAttributes = false,\n\t\tEmptyResponsePlaceholder = DefaultEmptyResponsePlaceholder,\n\t\tErrorResponsePlaceholder = DefaultErrorResponsePlaceholder,\n\t\tLoadingResponsePlaceholder = DefaultLoadingResponsePlaceholder,\n\t} = props;\n\n\tconst isMountedRef = useRef( true );\n\tconst [ showLoader, setShowLoader ] = useState( false );\n\tconst fetchRequestRef = useRef();\n\tconst [ response, setResponse ] = useState( null );\n\tconst prevProps = usePrevious( props );\n\tconst [ isLoading, setIsLoading ] = useState( false );\n\n\tfunction fetchData() {\n\t\tif ( ! isMountedRef.current ) {\n\t\t\treturn;\n\t\t}\n\n\t\tsetIsLoading( true );\n\n\t\tlet sanitizedAttributes =\n\t\t\tattributes &&\n\t\t\t__experimentalSanitizeBlockAttributes( block, attributes );\n\n\t\tif ( skipBlockSupportAttributes ) {\n\t\t\tsanitizedAttributes =\n\t\t\t\tremoveBlockSupportAttributes( sanitizedAttributes );\n\t\t}\n\n\t\t// If httpMethod is 'POST', send the attributes in the request body instead of the URL.\n\t\t// This allows sending a larger attributes object than in a GET request, where the attributes are in the URL.\n\t\tconst isPostRequest = 'POST' === httpMethod;\n\t\tconst urlAttributes = isPostRequest\n\t\t\t? null\n\t\t\t: sanitizedAttributes ?? null;\n\t\tconst path = rendererPath( block, urlAttributes, urlQueryArgs );\n\t\tconst data = isPostRequest\n\t\t\t? { attributes: sanitizedAttributes ?? null }\n\t\t\t: null;\n\n\t\t// Store the latest fetch request so that when we process it, we can\n\t\t// check if it is the current request, to avoid race conditions on slow networks.\n\t\tconst fetchRequest = ( fetchRequestRef.current = apiFetch( {\n\t\t\tpath,\n\t\t\tdata,\n\t\t\tmethod: isPostRequest ? 'POST' : 'GET',\n\t\t} )\n\t\t\t.then( ( fetchResponse ) => {\n\t\t\t\tif (\n\t\t\t\t\tisMountedRef.current &&\n\t\t\t\t\tfetchRequest === fetchRequestRef.current &&\n\t\t\t\t\tfetchResponse\n\t\t\t\t) {\n\t\t\t\t\tsetResponse( fetchResponse.rendered );\n\t\t\t\t}\n\t\t\t} )\n\t\t\t.catch( ( error ) => {\n\t\t\t\tif (\n\t\t\t\t\tisMountedRef.current &&\n\t\t\t\t\tfetchRequest === fetchRequestRef.current\n\t\t\t\t) {\n\t\t\t\t\tsetResponse( {\n\t\t\t\t\t\terror: true,\n\t\t\t\t\t\terrorMsg: error.message,\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t} )\n\t\t\t.finally( () => {\n\t\t\t\tif (\n\t\t\t\t\tisMountedRef.current &&\n\t\t\t\t\tfetchRequest === fetchRequestRef.current\n\t\t\t\t) {\n\t\t\t\t\tsetIsLoading( false );\n\t\t\t\t}\n\t\t\t} ) );\n\n\t\treturn fetchRequest;\n\t}\n\n\tconst debouncedFetchData = useDebounce( fetchData, 500 );\n\n\t// When the component unmounts, set isMountedRef to false. This will\n\t// let the async fetch callbacks know when to stop.\n\tuseEffect(\n\t\t() => () => {\n\t\t\tisMountedRef.current = false;\n\t\t},\n\t\t[]\n\t);\n\n\tuseEffect( () => {\n\t\t// Don't debounce the first fetch. This ensures that the first render\n\t\t// shows data as soon as possible.\n\t\tif ( prevProps === undefined ) {\n\t\t\tfetchData();\n\t\t} else if ( ! isEqual( prevProps, props ) ) {\n\t\t\tdebouncedFetchData();\n\t\t}\n\t} );\n\n\t/**\n\t * Effect to handle showing the loading placeholder.\n\t * Show it only if there is no previous response or\n\t * the request takes more than one second.\n\t */\n\tuseEffect( () => {\n\t\tif ( ! isLoading ) {\n\t\t\treturn;\n\t\t}\n\t\tconst timeout = setTimeout( () => {\n\t\t\tsetShowLoader( true );\n\t\t}, 1000 );\n\t\treturn () => clearTimeout( timeout );\n\t}, [ isLoading ] );\n\n\tconst hasResponse = !! response;\n\tconst hasEmptyResponse = response === '';\n\tconst hasError = response?.error;\n\n\tif ( isLoading ) {\n\t\treturn (\n\t\t\t<LoadingResponsePlaceholder { ...props } showLoader={ showLoader }>\n\t\t\t\t{ hasResponse && (\n\t\t\t\t\t<RawHTML className={ className }>{ response }</RawHTML>\n\t\t\t\t) }\n\t\t\t</LoadingResponsePlaceholder>\n\t\t);\n\t}\n\n\tif ( hasEmptyResponse || ! hasResponse ) {\n\t\treturn <EmptyResponsePlaceholder { ...props } />;\n\t}\n\n\tif ( hasError ) {\n\t\treturn <ErrorResponsePlaceholder response={ response } { ...props } />;\n\t}\n\n\treturn <RawHTML className={ className }>{ response }</RawHTML>;\n}\n"]}
@@ -16,6 +16,7 @@ import apiFetch from '@wordpress/api-fetch';
16
16
  import { addQueryArgs } from '@wordpress/url';
17
17
  import { Placeholder, Spinner } from '@wordpress/components';
18
18
  import { __experimentalSanitizeBlockAttributes } from '@wordpress/blocks';
19
+ const EMPTY_OBJECT = {};
19
20
  export function rendererPath(block) {
20
21
  let attributes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
21
22
  let urlQueryArgs = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
@@ -27,6 +28,29 @@ export function rendererPath(block) {
27
28
  ...urlQueryArgs
28
29
  });
29
30
  }
31
+ export function removeBlockSupportAttributes(attributes) {
32
+ const {
33
+ backgroundColor,
34
+ borderColor,
35
+ fontFamily,
36
+ fontSize,
37
+ gradient,
38
+ textColor,
39
+ className,
40
+ ...restAttributes
41
+ } = attributes;
42
+ const {
43
+ border,
44
+ color,
45
+ elements,
46
+ spacing,
47
+ typography,
48
+ ...restStyles
49
+ } = (attributes === null || attributes === void 0 ? void 0 : attributes.style) || EMPTY_OBJECT;
50
+ return { ...restAttributes,
51
+ style: restStyles
52
+ };
53
+ }
30
54
 
31
55
  function DefaultEmptyResponsePlaceholder(_ref) {
32
56
  let {
@@ -80,6 +104,7 @@ export default function ServerSideRender(props) {
80
104
  className,
81
105
  httpMethod = 'GET',
82
106
  urlQueryArgs,
107
+ skipBlockSupportAttributes = false,
83
108
  EmptyResponsePlaceholder = DefaultEmptyResponsePlaceholder,
84
109
  ErrorResponsePlaceholder = DefaultErrorResponsePlaceholder,
85
110
  LoadingResponsePlaceholder = DefaultLoadingResponsePlaceholder
@@ -92,21 +117,27 @@ export default function ServerSideRender(props) {
92
117
  const [isLoading, setIsLoading] = useState(false);
93
118
 
94
119
  function fetchData() {
120
+ var _sanitizedAttributes, _sanitizedAttributes2;
121
+
95
122
  if (!isMountedRef.current) {
96
123
  return;
97
124
  }
98
125
 
99
126
  setIsLoading(true);
100
127
 
101
- const sanitizedAttributes = attributes && __experimentalSanitizeBlockAttributes(block, attributes); // If httpMethod is 'POST', send the attributes in the request body instead of the URL.
128
+ let sanitizedAttributes = attributes && __experimentalSanitizeBlockAttributes(block, attributes);
129
+
130
+ if (skipBlockSupportAttributes) {
131
+ sanitizedAttributes = removeBlockSupportAttributes(sanitizedAttributes);
132
+ } // If httpMethod is 'POST', send the attributes in the request body instead of the URL.
102
133
  // This allows sending a larger attributes object than in a GET request, where the attributes are in the URL.
103
134
 
104
135
 
105
136
  const isPostRequest = 'POST' === httpMethod;
106
- const urlAttributes = isPostRequest ? null : sanitizedAttributes !== null && sanitizedAttributes !== void 0 ? sanitizedAttributes : null;
137
+ const urlAttributes = isPostRequest ? null : (_sanitizedAttributes = sanitizedAttributes) !== null && _sanitizedAttributes !== void 0 ? _sanitizedAttributes : null;
107
138
  const path = rendererPath(block, urlAttributes, urlQueryArgs);
108
139
  const data = isPostRequest ? {
109
- attributes: sanitizedAttributes !== null && sanitizedAttributes !== void 0 ? sanitizedAttributes : null
140
+ attributes: (_sanitizedAttributes2 = sanitizedAttributes) !== null && _sanitizedAttributes2 !== void 0 ? _sanitizedAttributes2 : null
110
141
  } : null; // Store the latest fetch request so that when we process it, we can
111
142
  // check if it is the current request, to avoid race conditions on slow networks.
112
143
 
@@ -1 +1 @@
1
- {"version":3,"sources":["@wordpress/server-side-render/src/server-side-render.js"],"names":["isEqual","useDebounce","usePrevious","RawHTML","useEffect","useRef","useState","__","sprintf","apiFetch","addQueryArgs","Placeholder","Spinner","__experimentalSanitizeBlockAttributes","rendererPath","block","attributes","urlQueryArgs","context","DefaultEmptyResponsePlaceholder","className","DefaultErrorResponsePlaceholder","response","errorMessage","errorMsg","DefaultLoadingResponsePlaceholder","children","showLoader","position","top","left","marginTop","marginLeft","opacity","ServerSideRender","props","httpMethod","EmptyResponsePlaceholder","ErrorResponsePlaceholder","LoadingResponsePlaceholder","isMountedRef","setShowLoader","fetchRequestRef","setResponse","prevProps","isLoading","setIsLoading","fetchData","current","sanitizedAttributes","isPostRequest","urlAttributes","path","data","fetchRequest","method","then","fetchResponse","rendered","catch","error","message","finally","debouncedFetchData","undefined","timeout","setTimeout","clearTimeout","hasResponse","hasEmptyResponse","hasError"],"mappings":"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","sourcesContent":["/**\n * External dependencies\n */\nimport { isEqual } from 'lodash';\n\n/**\n * WordPress dependencies\n */\nimport { useDebounce, usePrevious } from '@wordpress/compose';\nimport { RawHTML, useEffect, useRef, useState } from '@wordpress/element';\nimport { __, sprintf } from '@wordpress/i18n';\nimport apiFetch from '@wordpress/api-fetch';\nimport { addQueryArgs } from '@wordpress/url';\nimport { Placeholder, Spinner } from '@wordpress/components';\nimport { __experimentalSanitizeBlockAttributes } from '@wordpress/blocks';\n\nexport function rendererPath( block, attributes = null, urlQueryArgs = {} ) {\n\treturn addQueryArgs( `/wp/v2/block-renderer/${ block }`, {\n\t\tcontext: 'edit',\n\t\t...( null !== attributes ? { attributes } : {} ),\n\t\t...urlQueryArgs,\n\t} );\n}\n\nfunction DefaultEmptyResponsePlaceholder( { className } ) {\n\treturn (\n\t\t<Placeholder className={ className }>\n\t\t\t{ __( 'Block rendered as empty.' ) }\n\t\t</Placeholder>\n\t);\n}\n\nfunction DefaultErrorResponsePlaceholder( { response, className } ) {\n\tconst errorMessage = sprintf(\n\t\t// translators: %s: error message describing the problem\n\t\t__( 'Error loading block: %s' ),\n\t\tresponse.errorMsg\n\t);\n\treturn <Placeholder className={ className }>{ errorMessage }</Placeholder>;\n}\n\nfunction DefaultLoadingResponsePlaceholder( { children, showLoader } ) {\n\treturn (\n\t\t<div style={ { position: 'relative' } }>\n\t\t\t{ showLoader && (\n\t\t\t\t<div\n\t\t\t\t\tstyle={ {\n\t\t\t\t\t\tposition: 'absolute',\n\t\t\t\t\t\ttop: '50%',\n\t\t\t\t\t\tleft: '50%',\n\t\t\t\t\t\tmarginTop: '-9px',\n\t\t\t\t\t\tmarginLeft: '-9px',\n\t\t\t\t\t} }\n\t\t\t\t>\n\t\t\t\t\t<Spinner />\n\t\t\t\t</div>\n\t\t\t) }\n\t\t\t<div style={ { opacity: showLoader ? '0.3' : 1 } }>\n\t\t\t\t{ children }\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\nexport default function ServerSideRender( props ) {\n\tconst {\n\t\tattributes,\n\t\tblock,\n\t\tclassName,\n\t\thttpMethod = 'GET',\n\t\turlQueryArgs,\n\t\tEmptyResponsePlaceholder = DefaultEmptyResponsePlaceholder,\n\t\tErrorResponsePlaceholder = DefaultErrorResponsePlaceholder,\n\t\tLoadingResponsePlaceholder = DefaultLoadingResponsePlaceholder,\n\t} = props;\n\n\tconst isMountedRef = useRef( true );\n\tconst [ showLoader, setShowLoader ] = useState( false );\n\tconst fetchRequestRef = useRef();\n\tconst [ response, setResponse ] = useState( null );\n\tconst prevProps = usePrevious( props );\n\tconst [ isLoading, setIsLoading ] = useState( false );\n\n\tfunction fetchData() {\n\t\tif ( ! isMountedRef.current ) {\n\t\t\treturn;\n\t\t}\n\n\t\tsetIsLoading( true );\n\n\t\tconst sanitizedAttributes =\n\t\t\tattributes &&\n\t\t\t__experimentalSanitizeBlockAttributes( block, attributes );\n\n\t\t// If httpMethod is 'POST', send the attributes in the request body instead of the URL.\n\t\t// This allows sending a larger attributes object than in a GET request, where the attributes are in the URL.\n\t\tconst isPostRequest = 'POST' === httpMethod;\n\t\tconst urlAttributes = isPostRequest\n\t\t\t? null\n\t\t\t: sanitizedAttributes ?? null;\n\t\tconst path = rendererPath( block, urlAttributes, urlQueryArgs );\n\t\tconst data = isPostRequest\n\t\t\t? { attributes: sanitizedAttributes ?? null }\n\t\t\t: null;\n\n\t\t// Store the latest fetch request so that when we process it, we can\n\t\t// check if it is the current request, to avoid race conditions on slow networks.\n\t\tconst fetchRequest = ( fetchRequestRef.current = apiFetch( {\n\t\t\tpath,\n\t\t\tdata,\n\t\t\tmethod: isPostRequest ? 'POST' : 'GET',\n\t\t} )\n\t\t\t.then( ( fetchResponse ) => {\n\t\t\t\tif (\n\t\t\t\t\tisMountedRef.current &&\n\t\t\t\t\tfetchRequest === fetchRequestRef.current &&\n\t\t\t\t\tfetchResponse\n\t\t\t\t) {\n\t\t\t\t\tsetResponse( fetchResponse.rendered );\n\t\t\t\t}\n\t\t\t} )\n\t\t\t.catch( ( error ) => {\n\t\t\t\tif (\n\t\t\t\t\tisMountedRef.current &&\n\t\t\t\t\tfetchRequest === fetchRequestRef.current\n\t\t\t\t) {\n\t\t\t\t\tsetResponse( {\n\t\t\t\t\t\terror: true,\n\t\t\t\t\t\terrorMsg: error.message,\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t} )\n\t\t\t.finally( () => {\n\t\t\t\tif (\n\t\t\t\t\tisMountedRef.current &&\n\t\t\t\t\tfetchRequest === fetchRequestRef.current\n\t\t\t\t) {\n\t\t\t\t\tsetIsLoading( false );\n\t\t\t\t}\n\t\t\t} ) );\n\n\t\treturn fetchRequest;\n\t}\n\n\tconst debouncedFetchData = useDebounce( fetchData, 500 );\n\n\t// When the component unmounts, set isMountedRef to false. This will\n\t// let the async fetch callbacks know when to stop.\n\tuseEffect(\n\t\t() => () => {\n\t\t\tisMountedRef.current = false;\n\t\t},\n\t\t[]\n\t);\n\n\tuseEffect( () => {\n\t\t// Don't debounce the first fetch. This ensures that the first render\n\t\t// shows data as soon as possible.\n\t\tif ( prevProps === undefined ) {\n\t\t\tfetchData();\n\t\t} else if ( ! isEqual( prevProps, props ) ) {\n\t\t\tdebouncedFetchData();\n\t\t}\n\t} );\n\n\t/**\n\t * Effect to handle showing the loading placeholder.\n\t * Show it only if there is no previous response or\n\t * the request takes more than one second.\n\t */\n\tuseEffect( () => {\n\t\tif ( ! isLoading ) {\n\t\t\treturn;\n\t\t}\n\t\tconst timeout = setTimeout( () => {\n\t\t\tsetShowLoader( true );\n\t\t}, 1000 );\n\t\treturn () => clearTimeout( timeout );\n\t}, [ isLoading ] );\n\n\tconst hasResponse = !! response;\n\tconst hasEmptyResponse = response === '';\n\tconst hasError = response?.error;\n\n\tif ( isLoading ) {\n\t\treturn (\n\t\t\t<LoadingResponsePlaceholder { ...props } showLoader={ showLoader }>\n\t\t\t\t{ hasResponse && (\n\t\t\t\t\t<RawHTML className={ className }>{ response }</RawHTML>\n\t\t\t\t) }\n\t\t\t</LoadingResponsePlaceholder>\n\t\t);\n\t}\n\n\tif ( hasEmptyResponse || ! hasResponse ) {\n\t\treturn <EmptyResponsePlaceholder { ...props } />;\n\t}\n\n\tif ( hasError ) {\n\t\treturn <ErrorResponsePlaceholder response={ response } { ...props } />;\n\t}\n\n\treturn <RawHTML className={ className }>{ response }</RawHTML>;\n}\n"]}
1
+ {"version":3,"sources":["@wordpress/server-side-render/src/server-side-render.js"],"names":["isEqual","useDebounce","usePrevious","RawHTML","useEffect","useRef","useState","__","sprintf","apiFetch","addQueryArgs","Placeholder","Spinner","__experimentalSanitizeBlockAttributes","EMPTY_OBJECT","rendererPath","block","attributes","urlQueryArgs","context","removeBlockSupportAttributes","backgroundColor","borderColor","fontFamily","fontSize","gradient","textColor","className","restAttributes","border","color","elements","spacing","typography","restStyles","style","DefaultEmptyResponsePlaceholder","DefaultErrorResponsePlaceholder","response","errorMessage","errorMsg","DefaultLoadingResponsePlaceholder","children","showLoader","position","top","left","marginTop","marginLeft","opacity","ServerSideRender","props","httpMethod","skipBlockSupportAttributes","EmptyResponsePlaceholder","ErrorResponsePlaceholder","LoadingResponsePlaceholder","isMountedRef","setShowLoader","fetchRequestRef","setResponse","prevProps","isLoading","setIsLoading","fetchData","current","sanitizedAttributes","isPostRequest","urlAttributes","path","data","fetchRequest","method","then","fetchResponse","rendered","catch","error","message","finally","debouncedFetchData","undefined","timeout","setTimeout","clearTimeout","hasResponse","hasEmptyResponse","hasError"],"mappings":"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","sourcesContent":["/**\n * External dependencies\n */\nimport { isEqual } from 'lodash';\n\n/**\n * WordPress dependencies\n */\nimport { useDebounce, usePrevious } from '@wordpress/compose';\nimport { RawHTML, useEffect, useRef, useState } from '@wordpress/element';\nimport { __, sprintf } from '@wordpress/i18n';\nimport apiFetch from '@wordpress/api-fetch';\nimport { addQueryArgs } from '@wordpress/url';\nimport { Placeholder, Spinner } from '@wordpress/components';\nimport { __experimentalSanitizeBlockAttributes } from '@wordpress/blocks';\n\nconst EMPTY_OBJECT = {};\n\nexport function rendererPath( block, attributes = null, urlQueryArgs = {} ) {\n\treturn addQueryArgs( `/wp/v2/block-renderer/${ block }`, {\n\t\tcontext: 'edit',\n\t\t...( null !== attributes ? { attributes } : {} ),\n\t\t...urlQueryArgs,\n\t} );\n}\n\nexport function removeBlockSupportAttributes( attributes ) {\n\tconst {\n\t\tbackgroundColor,\n\t\tborderColor,\n\t\tfontFamily,\n\t\tfontSize,\n\t\tgradient,\n\t\ttextColor,\n\t\tclassName,\n\t\t...restAttributes\n\t} = attributes;\n\n\tconst { border, color, elements, spacing, typography, ...restStyles } =\n\t\tattributes?.style || EMPTY_OBJECT;\n\n\treturn {\n\t\t...restAttributes,\n\t\tstyle: restStyles,\n\t};\n}\n\nfunction DefaultEmptyResponsePlaceholder( { className } ) {\n\treturn (\n\t\t<Placeholder className={ className }>\n\t\t\t{ __( 'Block rendered as empty.' ) }\n\t\t</Placeholder>\n\t);\n}\n\nfunction DefaultErrorResponsePlaceholder( { response, className } ) {\n\tconst errorMessage = sprintf(\n\t\t// translators: %s: error message describing the problem\n\t\t__( 'Error loading block: %s' ),\n\t\tresponse.errorMsg\n\t);\n\treturn <Placeholder className={ className }>{ errorMessage }</Placeholder>;\n}\n\nfunction DefaultLoadingResponsePlaceholder( { children, showLoader } ) {\n\treturn (\n\t\t<div style={ { position: 'relative' } }>\n\t\t\t{ showLoader && (\n\t\t\t\t<div\n\t\t\t\t\tstyle={ {\n\t\t\t\t\t\tposition: 'absolute',\n\t\t\t\t\t\ttop: '50%',\n\t\t\t\t\t\tleft: '50%',\n\t\t\t\t\t\tmarginTop: '-9px',\n\t\t\t\t\t\tmarginLeft: '-9px',\n\t\t\t\t\t} }\n\t\t\t\t>\n\t\t\t\t\t<Spinner />\n\t\t\t\t</div>\n\t\t\t) }\n\t\t\t<div style={ { opacity: showLoader ? '0.3' : 1 } }>\n\t\t\t\t{ children }\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\nexport default function ServerSideRender( props ) {\n\tconst {\n\t\tattributes,\n\t\tblock,\n\t\tclassName,\n\t\thttpMethod = 'GET',\n\t\turlQueryArgs,\n\t\tskipBlockSupportAttributes = false,\n\t\tEmptyResponsePlaceholder = DefaultEmptyResponsePlaceholder,\n\t\tErrorResponsePlaceholder = DefaultErrorResponsePlaceholder,\n\t\tLoadingResponsePlaceholder = DefaultLoadingResponsePlaceholder,\n\t} = props;\n\n\tconst isMountedRef = useRef( true );\n\tconst [ showLoader, setShowLoader ] = useState( false );\n\tconst fetchRequestRef = useRef();\n\tconst [ response, setResponse ] = useState( null );\n\tconst prevProps = usePrevious( props );\n\tconst [ isLoading, setIsLoading ] = useState( false );\n\n\tfunction fetchData() {\n\t\tif ( ! isMountedRef.current ) {\n\t\t\treturn;\n\t\t}\n\n\t\tsetIsLoading( true );\n\n\t\tlet sanitizedAttributes =\n\t\t\tattributes &&\n\t\t\t__experimentalSanitizeBlockAttributes( block, attributes );\n\n\t\tif ( skipBlockSupportAttributes ) {\n\t\t\tsanitizedAttributes =\n\t\t\t\tremoveBlockSupportAttributes( sanitizedAttributes );\n\t\t}\n\n\t\t// If httpMethod is 'POST', send the attributes in the request body instead of the URL.\n\t\t// This allows sending a larger attributes object than in a GET request, where the attributes are in the URL.\n\t\tconst isPostRequest = 'POST' === httpMethod;\n\t\tconst urlAttributes = isPostRequest\n\t\t\t? null\n\t\t\t: sanitizedAttributes ?? null;\n\t\tconst path = rendererPath( block, urlAttributes, urlQueryArgs );\n\t\tconst data = isPostRequest\n\t\t\t? { attributes: sanitizedAttributes ?? null }\n\t\t\t: null;\n\n\t\t// Store the latest fetch request so that when we process it, we can\n\t\t// check if it is the current request, to avoid race conditions on slow networks.\n\t\tconst fetchRequest = ( fetchRequestRef.current = apiFetch( {\n\t\t\tpath,\n\t\t\tdata,\n\t\t\tmethod: isPostRequest ? 'POST' : 'GET',\n\t\t} )\n\t\t\t.then( ( fetchResponse ) => {\n\t\t\t\tif (\n\t\t\t\t\tisMountedRef.current &&\n\t\t\t\t\tfetchRequest === fetchRequestRef.current &&\n\t\t\t\t\tfetchResponse\n\t\t\t\t) {\n\t\t\t\t\tsetResponse( fetchResponse.rendered );\n\t\t\t\t}\n\t\t\t} )\n\t\t\t.catch( ( error ) => {\n\t\t\t\tif (\n\t\t\t\t\tisMountedRef.current &&\n\t\t\t\t\tfetchRequest === fetchRequestRef.current\n\t\t\t\t) {\n\t\t\t\t\tsetResponse( {\n\t\t\t\t\t\terror: true,\n\t\t\t\t\t\terrorMsg: error.message,\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t} )\n\t\t\t.finally( () => {\n\t\t\t\tif (\n\t\t\t\t\tisMountedRef.current &&\n\t\t\t\t\tfetchRequest === fetchRequestRef.current\n\t\t\t\t) {\n\t\t\t\t\tsetIsLoading( false );\n\t\t\t\t}\n\t\t\t} ) );\n\n\t\treturn fetchRequest;\n\t}\n\n\tconst debouncedFetchData = useDebounce( fetchData, 500 );\n\n\t// When the component unmounts, set isMountedRef to false. This will\n\t// let the async fetch callbacks know when to stop.\n\tuseEffect(\n\t\t() => () => {\n\t\t\tisMountedRef.current = false;\n\t\t},\n\t\t[]\n\t);\n\n\tuseEffect( () => {\n\t\t// Don't debounce the first fetch. This ensures that the first render\n\t\t// shows data as soon as possible.\n\t\tif ( prevProps === undefined ) {\n\t\t\tfetchData();\n\t\t} else if ( ! isEqual( prevProps, props ) ) {\n\t\t\tdebouncedFetchData();\n\t\t}\n\t} );\n\n\t/**\n\t * Effect to handle showing the loading placeholder.\n\t * Show it only if there is no previous response or\n\t * the request takes more than one second.\n\t */\n\tuseEffect( () => {\n\t\tif ( ! isLoading ) {\n\t\t\treturn;\n\t\t}\n\t\tconst timeout = setTimeout( () => {\n\t\t\tsetShowLoader( true );\n\t\t}, 1000 );\n\t\treturn () => clearTimeout( timeout );\n\t}, [ isLoading ] );\n\n\tconst hasResponse = !! response;\n\tconst hasEmptyResponse = response === '';\n\tconst hasError = response?.error;\n\n\tif ( isLoading ) {\n\t\treturn (\n\t\t\t<LoadingResponsePlaceholder { ...props } showLoader={ showLoader }>\n\t\t\t\t{ hasResponse && (\n\t\t\t\t\t<RawHTML className={ className }>{ response }</RawHTML>\n\t\t\t\t) }\n\t\t\t</LoadingResponsePlaceholder>\n\t\t);\n\t}\n\n\tif ( hasEmptyResponse || ! hasResponse ) {\n\t\treturn <EmptyResponsePlaceholder { ...props } />;\n\t}\n\n\tif ( hasError ) {\n\t\treturn <ErrorResponsePlaceholder response={ response } { ...props } />;\n\t}\n\n\treturn <RawHTML className={ className }>{ response }</RawHTML>;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wordpress/server-side-render",
3
- "version": "3.16.1-next.4d3b314fd5.0",
3
+ "version": "3.18.0",
4
4
  "description": "The component used with WordPress to server-side render a preview of dynamic blocks to display in the editor.",
5
5
  "author": "The WordPress Contributors",
6
6
  "license": "GPL-2.0-or-later",
@@ -27,15 +27,15 @@
27
27
  "react-native": "src/index",
28
28
  "dependencies": {
29
29
  "@babel/runtime": "^7.16.0",
30
- "@wordpress/api-fetch": "^6.15.1-next.4d3b314fd5.0",
31
- "@wordpress/blocks": "^11.18.1-next.4d3b314fd5.0",
32
- "@wordpress/components": "^21.1.2-next.4d3b314fd5.0",
33
- "@wordpress/compose": "^5.16.1-next.4d3b314fd5.0",
34
- "@wordpress/data": "^7.2.1-next.4d3b314fd5.0",
35
- "@wordpress/deprecated": "^3.18.1-next.4d3b314fd5.0",
36
- "@wordpress/element": "^4.16.1-next.4d3b314fd5.0",
37
- "@wordpress/i18n": "^4.18.1-next.4d3b314fd5.0",
38
- "@wordpress/url": "^3.19.1-next.4d3b314fd5.0",
30
+ "@wordpress/api-fetch": "^6.17.0",
31
+ "@wordpress/blocks": "^11.19.0",
32
+ "@wordpress/components": "^21.3.0",
33
+ "@wordpress/compose": "^5.18.0",
34
+ "@wordpress/data": "^7.4.0",
35
+ "@wordpress/deprecated": "^3.20.0",
36
+ "@wordpress/element": "^4.18.0",
37
+ "@wordpress/i18n": "^4.20.0",
38
+ "@wordpress/url": "^3.21.0",
39
39
  "lodash": "^4.17.21"
40
40
  },
41
41
  "peerDependencies": {
@@ -45,5 +45,5 @@
45
45
  "publishConfig": {
46
46
  "access": "public"
47
47
  },
48
- "gitHead": "25054766423cb49d959eb656c2533530073ff5c2"
48
+ "gitHead": "a2ff0e6471c88436dad0287beb88d1729aa6f5dd"
49
49
  }
@@ -14,6 +14,8 @@ import { addQueryArgs } from '@wordpress/url';
14
14
  import { Placeholder, Spinner } from '@wordpress/components';
15
15
  import { __experimentalSanitizeBlockAttributes } from '@wordpress/blocks';
16
16
 
17
+ const EMPTY_OBJECT = {};
18
+
17
19
  export function rendererPath( block, attributes = null, urlQueryArgs = {} ) {
18
20
  return addQueryArgs( `/wp/v2/block-renderer/${ block }`, {
19
21
  context: 'edit',
@@ -22,6 +24,27 @@ export function rendererPath( block, attributes = null, urlQueryArgs = {} ) {
22
24
  } );
23
25
  }
24
26
 
27
+ export function removeBlockSupportAttributes( attributes ) {
28
+ const {
29
+ backgroundColor,
30
+ borderColor,
31
+ fontFamily,
32
+ fontSize,
33
+ gradient,
34
+ textColor,
35
+ className,
36
+ ...restAttributes
37
+ } = attributes;
38
+
39
+ const { border, color, elements, spacing, typography, ...restStyles } =
40
+ attributes?.style || EMPTY_OBJECT;
41
+
42
+ return {
43
+ ...restAttributes,
44
+ style: restStyles,
45
+ };
46
+ }
47
+
25
48
  function DefaultEmptyResponsePlaceholder( { className } ) {
26
49
  return (
27
50
  <Placeholder className={ className }>
@@ -69,6 +92,7 @@ export default function ServerSideRender( props ) {
69
92
  className,
70
93
  httpMethod = 'GET',
71
94
  urlQueryArgs,
95
+ skipBlockSupportAttributes = false,
72
96
  EmptyResponsePlaceholder = DefaultEmptyResponsePlaceholder,
73
97
  ErrorResponsePlaceholder = DefaultErrorResponsePlaceholder,
74
98
  LoadingResponsePlaceholder = DefaultLoadingResponsePlaceholder,
@@ -88,10 +112,15 @@ export default function ServerSideRender( props ) {
88
112
 
89
113
  setIsLoading( true );
90
114
 
91
- const sanitizedAttributes =
115
+ let sanitizedAttributes =
92
116
  attributes &&
93
117
  __experimentalSanitizeBlockAttributes( block, attributes );
94
118
 
119
+ if ( skipBlockSupportAttributes ) {
120
+ sanitizedAttributes =
121
+ removeBlockSupportAttributes( sanitizedAttributes );
122
+ }
123
+
95
124
  // If httpMethod is 'POST', send the attributes in the request body instead of the URL.
96
125
  // This allows sending a larger attributes object than in a GET request, where the attributes are in the URL.
97
126
  const isPostRequest = 'POST' === httpMethod;
package/src/test/index.js CHANGED
@@ -1,7 +1,10 @@
1
1
  /**
2
2
  * Internal dependencies
3
3
  */
4
- import { rendererPath } from '../server-side-render';
4
+ import {
5
+ rendererPath,
6
+ removeBlockSupportAttributes,
7
+ } from '../server-side-render';
5
8
 
6
9
  describe( 'rendererPath', () => {
7
10
  test( 'should return an base path for empty input', () => {
@@ -75,4 +78,66 @@ describe( 'rendererPath', () => {
75
78
  '/wp/v2/block-renderer/core/test-block?context=edit&attributes%5BstringArg%5D=test&id=1234'
76
79
  );
77
80
  } );
81
+
82
+ test( 'Should remove attributes and style properties applied by the block supports', () => {
83
+ expect(
84
+ removeBlockSupportAttributes( {
85
+ backgroundColor: 'foreground',
86
+ borderColor: 'foreground',
87
+ fontFamily: 'system-font',
88
+ fontSize: 'small',
89
+ gradient: 'vivid-cyan-blue-to-vivid-purple',
90
+ textColor: 'foreground',
91
+ customAttribute: 'customAttribute',
92
+ className: 'custom-class',
93
+ style: {
94
+ border: {
95
+ radius: '10px',
96
+ style: 'solid',
97
+ width: '10px',
98
+ },
99
+ color: {
100
+ background: '#000000',
101
+ text: '#000000',
102
+ },
103
+ elements: {
104
+ link: {
105
+ color: {
106
+ text: '#000000',
107
+ },
108
+ },
109
+ },
110
+ spacing: {
111
+ margin: {
112
+ top: '10px',
113
+ right: '10px',
114
+ bottom: '10px',
115
+ left: '10px',
116
+ },
117
+ padding: {
118
+ top: '10px',
119
+ right: '10px',
120
+ bottom: '10px',
121
+ left: '10px',
122
+ },
123
+ },
124
+ typography: {
125
+ fontSize: '10px',
126
+ fontStyle: 'normal',
127
+ fontWeight: '500',
128
+ letterSpacing: '10px',
129
+ lineHeight: '1',
130
+ textDecoration: 'line-through',
131
+ textTransform: 'uppercase',
132
+ },
133
+ customStyle: 'customStyle',
134
+ },
135
+ } )
136
+ ).toEqual( {
137
+ customAttribute: 'customAttribute',
138
+ style: {
139
+ customStyle: 'customStyle',
140
+ },
141
+ } );
142
+ } );
78
143
  } );