PluginProbe
Gutenberg / 21.8.2
Gutenberg v21.8.2
24.0.0 23.9.1 23.9.0 23.8.0 23.7.2 23.7.1 23.7.0 23.6.1 23.6.2 23.6.0 23.5.3 23.5.2 23.5.1 23.5.0 23.4.0 23.3.2 23.3.1 23.3.0 23.2.0 23.2.1 23.2.2 23.1.1 23.1.0 23.0.1 12.6.0 All 403 releases
gutenberg / build / server-side-render / index.js

index.js in Gutenberg 21.8.2, at build/server-side-render/index.js

435 lines 15.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /******/ (() => { // webpackBootstrap
2 /******/ "use strict";
3 /******/ // The require scope
4 /******/ var __webpack_require__ = {};
5 /******/
6 /************************************************************************/
7 /******/ /* webpack/runtime/compat get default export */
8 /******/ (() => {
9 /******/ // getDefaultExport function for compatibility with non-harmony modules
10 /******/ __webpack_require__.n = (module) => {
11 /******/ var getter = module && module.__esModule ?
12 /******/ () => (module['default']) :
13 /******/ () => (module);
14 /******/ __webpack_require__.d(getter, { a: getter });
15 /******/ return getter;
16 /******/ };
17 /******/ })();
18 /******/
19 /******/ /* webpack/runtime/define property getters */
20 /******/ (() => {
21 /******/ // define getter functions for harmony exports
22 /******/ __webpack_require__.d = (exports, definition) => {
23 /******/ for(var key in definition) {
24 /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
25 /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
26 /******/ }
27 /******/ }
28 /******/ };
29 /******/ })();
30 /******/
31 /******/ /* webpack/runtime/hasOwnProperty shorthand */
32 /******/ (() => {
33 /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
34 /******/ })();
35 /******/
36 /************************************************************************/
37 var __webpack_exports__ = {};
38
39 // EXPORTS
40 __webpack_require__.d(__webpack_exports__, {
41 "default": () => (/* binding */ build_module)
42 });
43
44 // UNUSED EXPORTS: ServerSideRender, useServerSideRender
45
46 ;// external ["wp","element"]
47 const external_wp_element_namespaceObject = window["wp"]["element"];
48 ;// external ["wp","i18n"]
49 const external_wp_i18n_namespaceObject = window["wp"]["i18n"];
50 ;// external ["wp","components"]
51 const external_wp_components_namespaceObject = window["wp"]["components"];
52 ;// external ["wp","data"]
53 const external_wp_data_namespaceObject = window["wp"]["data"];
54 ;// external ["wp","compose"]
55 const external_wp_compose_namespaceObject = window["wp"]["compose"];
56 ;// external ["wp","apiFetch"]
57 const external_wp_apiFetch_namespaceObject = window["wp"]["apiFetch"];
58 var external_wp_apiFetch_default = /*#__PURE__*/__webpack_require__.n(external_wp_apiFetch_namespaceObject);
59 ;// external ["wp","url"]
60 const external_wp_url_namespaceObject = window["wp"]["url"];
61 ;// external ["wp","blocks"]
62 const external_wp_blocks_namespaceObject = window["wp"]["blocks"];
63 ;// ./packages/server-side-render/build-module/hook.js
64 /**
65 * WordPress dependencies
66 */
67
68
69
70
71
72 function rendererPath(block, attributes = null, urlQueryArgs = {}) {
73 return (0,external_wp_url_namespaceObject.addQueryArgs)(`/wp/v2/block-renderer/${block}`, {
74 context: 'edit',
75 ...(null !== attributes ? {
76 attributes
77 } : {}),
78 ...urlQueryArgs
79 });
80 }
81 function removeBlockSupportAttributes(attributes) {
82 const {
83 backgroundColor,
84 borderColor,
85 fontFamily,
86 fontSize,
87 gradient,
88 textColor,
89 className,
90 ...restAttributes
91 } = attributes;
92 const {
93 border,
94 color,
95 elements,
96 shadow,
97 spacing,
98 typography,
99 ...restStyles
100 } = attributes?.style || {};
101 return {
102 ...restAttributes,
103 style: restStyles
104 };
105 }
106
107 /**
108 * @typedef {Object} ServerSideRenderResponse
109 * @property {string} status - The current request status: 'idle', 'loading', 'success', or 'error'.
110 * @property {string} [content] - The rendered block content (available when status is 'success').
111 * @property {string} [error] - The error message (available when status is 'error').
112 */
113
114 /**
115 * A hook for server-side rendering a preview of dynamic blocks to display in the editor.
116 *
117 * Handles fetching server-rendered previews for blocks, managing loading states,
118 * and automatically debouncing requests to prevent excessive API calls. It supports both
119 * GET and POST requests, with POST requests used for larger attribute payloads.
120 *
121 * @example
122 * Basic usage:
123 *
124 * ```jsx
125 * import { RawHTML } from '@wordpress/element';
126 * import { useServerSideRender } from '@wordpress/server-side-render';
127 *
128 * function MyServerSideRender( { attributes, block } ) {
129 * const { content, status, error } = useServerSideRender( {
130 * attributes,
131 * block,
132 * } );
133 *
134 * if ( status === 'loading' ) {
135 * return <div>Loading...</div>;
136 * }
137 *
138 * if ( status === 'error' ) {
139 * return <div>Error: { error }</div>;
140 * }
141 *
142 * return <RawHTML>{ content }</RawHTML>;
143 * }
144 * ```
145 *
146 * @param {Object} args The hook configuration object.
147 * @param {Object} args.attributes The block attributes to be sent to the server for rendering.
148 * @param {string} args.block The identifier of the block to be serverside rendered. Example: 'core/archives'.
149 * @param {boolean} [args.skipBlockSupportAttributes=false] Whether to remove block support attributes before sending.
150 * @param {string} [args.httpMethod='GET'] The HTTP method to use ('GET' or 'POST'). Default is 'GET'.
151 * @param {Object} [args.urlQueryArgs] Additional query arguments to append to the request URL.
152 *
153 * @return {ServerSideRenderResponse} The server-side render response object.
154 */
155 function useServerSideRender(args) {
156 var _sanitizedAttributes;
157 const [response, setResponse] = (0,external_wp_element_namespaceObject.useState)({
158 status: 'idle'
159 });
160 const shouldDebounceRef = (0,external_wp_element_namespaceObject.useRef)(false);
161 const {
162 attributes,
163 block,
164 skipBlockSupportAttributes = false,
165 httpMethod = 'GET',
166 urlQueryArgs
167 } = args;
168 let sanitizedAttributes = attributes && (0,external_wp_blocks_namespaceObject.__experimentalSanitizeBlockAttributes)(block, attributes);
169 if (skipBlockSupportAttributes) {
170 sanitizedAttributes = removeBlockSupportAttributes(sanitizedAttributes);
171 }
172
173 // If httpMethod is 'POST', send the attributes in the request body instead of the URL.
174 // This allows sending a larger attributes object than in a GET request, where the attributes are in the URL.
175 const isPostRequest = 'POST' === httpMethod;
176 const urlAttributes = isPostRequest ? null : sanitizedAttributes;
177 const path = rendererPath(block, urlAttributes, urlQueryArgs);
178 const body = isPostRequest ? JSON.stringify({
179 attributes: (_sanitizedAttributes = sanitizedAttributes) !== null && _sanitizedAttributes !== void 0 ? _sanitizedAttributes : null
180 }) : undefined;
181 (0,external_wp_element_namespaceObject.useEffect)(() => {
182 const controller = new AbortController();
183 const debouncedFetch = (0,external_wp_compose_namespaceObject.debounce)(function () {
184 {
185 setResponse({
186 status: 'loading'
187 });
188 external_wp_apiFetch_default()({
189 path,
190 method: isPostRequest ? 'POST' : 'GET',
191 body,
192 headers: isPostRequest ? {
193 'Content-Type': 'application/json'
194 } : {},
195 signal: controller.signal
196 }).then(res => {
197 setResponse({
198 status: 'success',
199 content: res ? res.rendered : ''
200 });
201 }).catch(error => {
202 // The request was aborted, do not update the response.
203 if (error.name === 'AbortError') {
204 return;
205 }
206 setResponse({
207 status: 'error',
208 error: error.message
209 });
210 }).finally(() => {
211 // Debounce requests after first fetch.
212 shouldDebounceRef.current = true;
213 });
214 }
215 }, shouldDebounceRef.current ? 500 : 0);
216 debouncedFetch();
217 return () => {
218 controller.abort();
219 debouncedFetch.cancel();
220 };
221 }, [path, isPostRequest, body]);
222 return response;
223 }
224
225 ;// external "ReactJSXRuntime"
226 const external_ReactJSXRuntime_namespaceObject = window["ReactJSXRuntime"];
227 ;// ./packages/server-side-render/build-module/server-side-render.js
228 /**
229 * WordPress dependencies
230 */
231
232
233
234
235
236 /**
237 * Internal dependencies
238 */
239
240
241 const EMPTY_OBJECT = {};
242 function DefaultEmptyResponsePlaceholder({
243 className
244 }) {
245 return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Placeholder, {
246 className: className,
247 children: (0,external_wp_i18n_namespaceObject.__)('Block rendered as empty.')
248 });
249 }
250 function DefaultErrorResponsePlaceholder({
251 message,
252 className
253 }) {
254 const errorMessage = (0,external_wp_i18n_namespaceObject.sprintf)(
255 // translators: %s: error message describing the problem
256 (0,external_wp_i18n_namespaceObject.__)('Error loading block: %s'), message);
257 return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Placeholder, {
258 className: className,
259 children: errorMessage
260 });
261 }
262 function DefaultLoadingResponsePlaceholder({
263 children
264 }) {
265 const [showLoader, setShowLoader] = (0,external_wp_element_namespaceObject.useState)(false);
266 (0,external_wp_element_namespaceObject.useEffect)(() => {
267 // Schedule showing the Spinner after 1 second.
268 const timeout = setTimeout(() => {
269 setShowLoader(true);
270 }, 1000);
271 return () => clearTimeout(timeout);
272 }, []);
273 return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)("div", {
274 style: {
275 position: 'relative'
276 },
277 children: [showLoader && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("div", {
278 style: {
279 position: 'absolute',
280 top: '50%',
281 left: '50%',
282 marginTop: '-9px',
283 marginLeft: '-9px'
284 },
285 children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Spinner, {})
286 }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("div", {
287 style: {
288 opacity: showLoader ? '0.3' : 1
289 },
290 children: children
291 })]
292 });
293 }
294 function ServerSideRender(props) {
295 const prevContentRef = (0,external_wp_element_namespaceObject.useRef)('');
296 const {
297 className,
298 EmptyResponsePlaceholder = DefaultEmptyResponsePlaceholder,
299 ErrorResponsePlaceholder = DefaultErrorResponsePlaceholder,
300 LoadingResponsePlaceholder = DefaultLoadingResponsePlaceholder,
301 ...restProps
302 } = props;
303 const {
304 content,
305 status,
306 error
307 } = useServerSideRender(restProps);
308
309 // Store the previous successful HTML response to show while loading.
310 (0,external_wp_element_namespaceObject.useEffect)(() => {
311 if (content) {
312 prevContentRef.current = content;
313 }
314 }, [content]);
315 if (status === 'loading') {
316 return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(LoadingResponsePlaceholder, {
317 ...props,
318 children: !!prevContentRef.current && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_element_namespaceObject.RawHTML, {
319 className: className,
320 children: prevContentRef.current
321 })
322 });
323 }
324 if (status === 'success' && !content) {
325 return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(EmptyResponsePlaceholder, {
326 ...props
327 });
328 }
329 if (status === 'error') {
330 return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(ErrorResponsePlaceholder, {
331 message: error,
332 ...props
333 });
334 }
335 return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_element_namespaceObject.RawHTML, {
336 className: className,
337 children: content
338 });
339 }
340
341 /**
342 * A component that renders server-side content for blocks.
343 *
344 * Note: URL query will include the current post ID when applicable.
345 * This is useful for blocks that depend on the context of the current post for rendering.
346 *
347 * @example
348 * ```jsx
349 * import { ServerSideRender } from '@wordpress/server-side-render';
350 * // Legacy import for WordPress 6.8 and earlier
351 * // import { default as ServerSideRender } from '@wordpress/server-side-render';
352 *
353 * function Example() {
354 * return (
355 * <ServerSideRender
356 * block="core/archives"
357 * attributes={ { showPostCounts: true } }
358 * urlQueryArgs={ { customArg: 'value' } }
359 * className="custom-class"
360 * />
361 * );
362 * }
363 * ```
364 *
365 * @param {Object} props Component props.
366 * @param {string} props.block The identifier of the block to be serverside rendered.
367 * @param {Object} props.attributes The block attributes to be sent to the server for rendering.
368 * @param {string} [props.className] Additional classes to apply to the wrapper element.
369 * @param {string} [props.httpMethod='GET'] The HTTP method to use ('GET' or 'POST'). Default is 'GET'
370 * @param {Object} [props.urlQueryArgs] Additional query arguments to append to the request URL.
371 * @param {boolean} [props.skipBlockSupportAttributes=false] Whether to remove block support attributes before sending.
372 * @param {Function} [props.EmptyResponsePlaceholder] Component rendered when the API response is empty.
373 * @param {Function} [props.ErrorResponsePlaceholder] Component rendered when the API response is an error.
374 * @param {Function} [props.LoadingResponsePlaceholder] Component rendered while the API request is loading.
375 *
376 * @return {JSX.Element} The rendered server-side content.
377 */
378 function ServerSideRenderWithPostId({
379 urlQueryArgs = EMPTY_OBJECT,
380 ...props
381 }) {
382 const currentPostId = (0,external_wp_data_namespaceObject.useSelect)(select => {
383 // FIXME: @wordpress/server-side-render should not depend on @wordpress/editor.
384 // It is used by blocks that can be loaded into a *non-post* block editor.
385 // eslint-disable-next-line @wordpress/data-no-store-string-literals
386 const postId = select('core/editor')?.getCurrentPostId();
387
388 // For templates and template parts we use a custom ID format.
389 // Since they aren't real posts, we don't want to use their ID
390 // for server-side rendering. Since they use a string based ID,
391 // we can assume real post IDs are numbers.
392 return postId && typeof postId === 'number' ? postId : null;
393 }, []);
394 const newUrlQueryArgs = (0,external_wp_element_namespaceObject.useMemo)(() => {
395 if (!currentPostId) {
396 return urlQueryArgs;
397 }
398 return {
399 post_id: currentPostId,
400 ...urlQueryArgs
401 };
402 }, [currentPostId, urlQueryArgs]);
403 return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(ServerSideRender, {
404 urlQueryArgs: newUrlQueryArgs,
405 ...props
406 });
407 }
408
409 ;// ./packages/server-side-render/build-module/index.js
410 /**
411 * Internal dependencies
412 */
413
414
415
416 /**
417 * A compatibility layer for the `ServerSideRender` component when used with `wp` global namespace.
418 *
419 * @deprecated Use `ServerSideRender` non-default export instead.
420 *
421 * @example
422 * ```js
423 * import ServerSideRender from '@wordpress/server-side-render';
424 * ```
425 */
426 const ServerSideRenderCompat = ServerSideRenderWithPostId;
427 ServerSideRenderCompat.ServerSideRender = ServerSideRenderWithPostId;
428 ServerSideRenderCompat.useServerSideRender = useServerSideRender;
429
430
431 /* harmony default export */ const build_module = (ServerSideRenderCompat);
432
433 (window.wp = window.wp || {}).serverSideRender = __webpack_exports__["default"];
434 /******/ })()
435 ;