From 57864b751f4e51563179282baaf9056b85a6e6d5 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Tue, 14 May 2024 16:42:26 +0200 Subject: [PATCH 01/12] Add script module data implementation Use it for Interactivity API store data passing --- .../class-wp-interactivity-api.php | 16 ++------- lib/experimental/script-modules.php | 33 +++++++++++++++++++ packages/interactivity/src/store.ts | 12 +++---- 3 files changed, 40 insertions(+), 21 deletions(-) diff --git a/lib/compat/wordpress-6.5/interactivity-api/class-wp-interactivity-api.php b/lib/compat/wordpress-6.5/interactivity-api/class-wp-interactivity-api.php index d0661d7585726..bcc2634ce7b3a 100644 --- a/lib/compat/wordpress-6.5/interactivity-api/class-wp-interactivity-api.php +++ b/lib/compat/wordpress-6.5/interactivity-api/class-wp-interactivity-api.php @@ -167,18 +167,7 @@ public function print_client_interactivity_data() { $interactivity_data['state'] = $state; } - if ( ! empty( $interactivity_data ) ) { - wp_print_inline_script_tag( - wp_json_encode( - $interactivity_data, - JSON_HEX_TAG | JSON_HEX_AMP - ), - array( - 'type' => 'application/json', - 'id' => 'wp-interactivity-data', - ) - ); - } + return $interactivity_data; } /** @@ -207,8 +196,7 @@ public function register_script_modules() { * @since 6.5.0 */ public function add_hooks() { - add_action( 'wp_enqueue_scripts', array( $this, 'register_script_modules' ) ); - add_action( 'wp_footer', array( $this, 'print_client_interactivity_data' ) ); + add_filter( 'gb_scriptmoduledata_@wordpress/interactivity', array( $this, 'print_client_interactivity_data' ) ); } /** diff --git a/lib/experimental/script-modules.php b/lib/experimental/script-modules.php index e22b757c11950..8f709e3cdd723 100644 --- a/lib/experimental/script-modules.php +++ b/lib/experimental/script-modules.php @@ -197,3 +197,36 @@ function gutenberg_dequeue_module( $module_identifier ) { _deprecated_function( __FUNCTION__, 'Gutenberg 17.6.0', 'wp_dequeue_script_module' ); wp_script_modules()->dequeue( $module_identifier ); } + + +/** + * @since 18.4.0 + */ +function gutenberg_print_script_module_data(): void { + $get_marked_for_enqueue = new ReflectionMethod( 'WP_Script_Modules', 'get_marked_for_enqueue' ); + $get_import_map = new ReflectionMethod( 'WP_Script_Modules', 'get_import_map' ); + + $modules = array(); + foreach ( array_keys( $get_marked_for_enqueue->invoke( wp_script_modules() ) ) as $id ) { + $modules[ $id ] = true; + } + foreach ( array_keys( $get_import_map->invoke( wp_script_modules() )['imports'] ) as $id ) { + $modules[ $id ] = true; + } + + foreach ( array_keys( $modules ) as $module_id ) { + $config = apply_filters( 'gb_scriptmoduledata_' . $module_id, array() ); + if ( ! empty( $config ) ) { + wp_print_inline_script_tag( + wp_json_encode( $config, JSON_HEX_TAG | JSON_HEX_AMP ), + array( + 'type' => 'application/json', + 'id' => 'gb-scriptmodule-data_' . $module_id, + ) + ); + } + } +} + +add_action( 'wp_footer', 'gutenberg_print_script_module_data' ); +add_action( 'admin_print_footer_scripts', 'gutenberg_print_script_module_data' ); diff --git a/packages/interactivity/src/store.ts b/packages/interactivity/src/store.ts index 9b35192fe8b13..32f32ecd6b625 100644 --- a/packages/interactivity/src/store.ts +++ b/packages/interactivity/src/store.ts @@ -319,15 +319,13 @@ export function store( } export const parseInitialData = ( dom = document ) => { - const storeTag = dom.querySelector( - `script[type="application/json"]#wp-interactivity-data` + const jsonDataScriptTag = dom.getElementById( + 'gb-scriptmodule-data_@wordpress/interactivity' ); - if ( storeTag?.textContent ) { + if ( jsonDataScriptTag?.textContent ) { try { - return JSON.parse( storeTag.textContent ); - } catch ( e ) { - // Do nothing. - } + return JSON.parse( jsonDataScriptTag.textContent ); + } catch {} } return {}; }; From e2f1a6ac512c77a1e81a2decef9cebeb182bafea Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Tue, 14 May 2024 16:52:12 +0200 Subject: [PATCH 02/12] Better JSON encoding See https://github.com/WordPress/wordpress-develop/pull/6520 --- lib/experimental/script-modules.php | 49 +++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/lib/experimental/script-modules.php b/lib/experimental/script-modules.php index 8f709e3cdd723..b17054fd74966 100644 --- a/lib/experimental/script-modules.php +++ b/lib/experimental/script-modules.php @@ -215,10 +215,53 @@ function gutenberg_print_script_module_data(): void { } foreach ( array_keys( $modules ) as $module_id ) { - $config = apply_filters( 'gb_scriptmoduledata_' . $module_id, array() ); - if ( ! empty( $config ) ) { + $data = apply_filters( 'gb_scriptmoduledata_' . $module_id, array() ); + if ( ! empty( $data ) ) { + /* + * This data will be printed as JSON inside a script tag like this: + * + * + * A script tag must be closed by a sequence beginning with `` will be printed as `\u003C/script\u00E3`. + * + * - JSON_HEX_TAG: All < and > are converted to \u003C and \u003E. + * - JSON_UNESCAPED_SLASHES: Don't escape /. + * + * @see https://www.php.net/manual/en/json.constants.php for details on these constants. + * @see https://html.spec.whatwg.org/#script-data-state for details on script + * tag parsing. + */ + $json_encode_flags = JSON_HEX_TAG | JSON_UNESCAPED_SLASHES; + if ( 'UTF-8' === get_option( 'blog_charset' ) ) { + /* + * If the page will use UTF-8 encoding, it's safe to print unescaped unicode in + * JSON. Set the following flags: + * + * - JSON_UNESCAPED_UNICODE: Encode multibyte Unicode characters literally + * (default is to escape as \uXXXX). + * - JSON_UNESCAPED_LINE_TERMINATORS: The line terminators are kept unescaped when + * JSON_UNESCAPED_UNICODE is supplied. It uses the same behaviour as it was + * before PHP 7.1 without this constant. Available as of PHP 7.1.0. + * + * The JSON specification does not specify a character encoding, RFC-8259 + * suggests that UTF-8 be used everywhere. It's risky to print unicode if the page + * uses any other encoding. + * + * > JSON text exchanged between systems that are not part of a closed ecosystem + * > MUST be encoded using UTF-8. Previous specifications of JSON have not required + * > the use of UTF-8 when transmitting JSON text. However, the vast majority of + * > JSON- based software implementations have chosen to use the UTF-8 encoding, + * > to the extent that it is the only encoding that achieves interoperability. + * + * @see https://www.rfc-editor.org/rfc/rfc8259.html + * + */ + $json_encode_flags |= JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_LINE_TERMINATORS; + } + wp_print_inline_script_tag( - wp_json_encode( $config, JSON_HEX_TAG | JSON_HEX_AMP ), + wp_json_encode( $data, $json_encode_flags ), array( 'type' => 'application/json', 'id' => 'gb-scriptmodule-data_' . $module_id, From 9afd8e9263618840d8f1b3722cd08c2ccc406e40 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Tue, 14 May 2024 17:13:55 +0200 Subject: [PATCH 03/12] Use expected core filter name and element ID --- .../interactivity-api/class-wp-interactivity-api.php | 2 +- lib/experimental/script-modules.php | 4 ++-- packages/interactivity/src/store.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/compat/wordpress-6.5/interactivity-api/class-wp-interactivity-api.php b/lib/compat/wordpress-6.5/interactivity-api/class-wp-interactivity-api.php index bcc2634ce7b3a..34f022f488a58 100644 --- a/lib/compat/wordpress-6.5/interactivity-api/class-wp-interactivity-api.php +++ b/lib/compat/wordpress-6.5/interactivity-api/class-wp-interactivity-api.php @@ -196,7 +196,7 @@ public function register_script_modules() { * @since 6.5.0 */ public function add_hooks() { - add_filter( 'gb_scriptmoduledata_@wordpress/interactivity', array( $this, 'print_client_interactivity_data' ) ); + add_filter( 'scriptmoduledata_@wordpress/interactivity', array( $this, 'print_client_interactivity_data' ) ); } /** diff --git a/lib/experimental/script-modules.php b/lib/experimental/script-modules.php index b17054fd74966..a210f06362d44 100644 --- a/lib/experimental/script-modules.php +++ b/lib/experimental/script-modules.php @@ -215,7 +215,7 @@ function gutenberg_print_script_module_data(): void { } foreach ( array_keys( $modules ) as $module_id ) { - $data = apply_filters( 'gb_scriptmoduledata_' . $module_id, array() ); + $data = apply_filters( 'scriptmoduledata_' . $module_id, array() ); if ( ! empty( $data ) ) { /* * This data will be printed as JSON inside a script tag like this: @@ -264,7 +264,7 @@ function gutenberg_print_script_module_data(): void { wp_json_encode( $data, $json_encode_flags ), array( 'type' => 'application/json', - 'id' => 'gb-scriptmodule-data_' . $module_id, + 'id' => 'wp-scriptmodule-data_' . $module_id, ) ); } diff --git a/packages/interactivity/src/store.ts b/packages/interactivity/src/store.ts index 32f32ecd6b625..c55ee76edb6e6 100644 --- a/packages/interactivity/src/store.ts +++ b/packages/interactivity/src/store.ts @@ -320,7 +320,7 @@ export function store( export const parseInitialData = ( dom = document ) => { const jsonDataScriptTag = dom.getElementById( - 'gb-scriptmodule-data_@wordpress/interactivity' + 'wp-scriptmodule-data_@wordpress/interactivity' ); if ( jsonDataScriptTag?.textContent ) { try { From bf4273fbc0f1a693e8a0507abb82a86be2221b77 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Tue, 14 May 2024 17:14:21 +0200 Subject: [PATCH 04/12] Add fallback to previous element ID for iAPI store data --- packages/interactivity/src/store.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/interactivity/src/store.ts b/packages/interactivity/src/store.ts index c55ee76edb6e6..f6366283d2d6a 100644 --- a/packages/interactivity/src/store.ts +++ b/packages/interactivity/src/store.ts @@ -319,9 +319,11 @@ export function store( } export const parseInitialData = ( dom = document ) => { - const jsonDataScriptTag = dom.getElementById( - 'wp-scriptmodule-data_@wordpress/interactivity' - ); + const jsonDataScriptTag = + // Preferred Script Module data passing form + dom.getElementById( 'wp-scriptmodule-data_@wordpress/interactivity' ) ?? + // Legacy form + dom.getElementById( 'wp-interactivity-data' ); if ( jsonDataScriptTag?.textContent ) { try { return JSON.parse( jsonDataScriptTag.textContent ); From adfd99dbe796350a2aeab1135f5be2bc8741b2f6 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Wed, 15 May 2024 09:21:55 +0200 Subject: [PATCH 05/12] Restore Interactivity Script Module enqueue --- .../interactivity-api/class-wp-interactivity-api.php | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/compat/wordpress-6.5/interactivity-api/class-wp-interactivity-api.php b/lib/compat/wordpress-6.5/interactivity-api/class-wp-interactivity-api.php index 34f022f488a58..0e350487f9b86 100644 --- a/lib/compat/wordpress-6.5/interactivity-api/class-wp-interactivity-api.php +++ b/lib/compat/wordpress-6.5/interactivity-api/class-wp-interactivity-api.php @@ -196,6 +196,7 @@ public function register_script_modules() { * @since 6.5.0 */ public function add_hooks() { + add_action( 'wp_enqueue_scripts', array( $this, 'register_script_modules' ) ); add_filter( 'scriptmoduledata_@wordpress/interactivity', array( $this, 'print_client_interactivity_data' ) ); } From 948c3afb79b5325c2b9c34ee5f08b94f1bb69490 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Wed, 15 May 2024 09:22:16 +0200 Subject: [PATCH 06/12] Fix whitespace --- lib/experimental/script-modules.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/experimental/script-modules.php b/lib/experimental/script-modules.php index a210f06362d44..0b38e7aed0216 100644 --- a/lib/experimental/script-modules.php +++ b/lib/experimental/script-modules.php @@ -217,7 +217,7 @@ function gutenberg_print_script_module_data(): void { foreach ( array_keys( $modules ) as $module_id ) { $data = apply_filters( 'scriptmoduledata_' . $module_id, array() ); if ( ! empty( $data ) ) { - /* + /* * This data will be printed as JSON inside a script tag like this: * * From 8c9fe0f5df16ad616bd33f42859efec7027d1117 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Wed, 15 May 2024 12:16:06 +0200 Subject: [PATCH 07/12] Fix dynamic filter name according to convention Co-authored-by: Bernie Reiter <96308+ockham@users.noreply.github.com> --- lib/experimental/script-modules.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/experimental/script-modules.php b/lib/experimental/script-modules.php index 0b38e7aed0216..60460bc3698d6 100644 --- a/lib/experimental/script-modules.php +++ b/lib/experimental/script-modules.php @@ -215,7 +215,7 @@ function gutenberg_print_script_module_data(): void { } foreach ( array_keys( $modules ) as $module_id ) { - $data = apply_filters( 'scriptmoduledata_' . $module_id, array() ); + $data = apply_filters( "scriptmoduledata_{$module_id}", array() ); if ( ! empty( $data ) ) { /* * This data will be printed as JSON inside a script tag like this: From 79a68bb522cc408aab8e02beeebe32bf08571797 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Wed, 15 May 2024 13:10:46 +0200 Subject: [PATCH 08/12] Better documentation --- lib/experimental/script-modules.php | 31 +++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/lib/experimental/script-modules.php b/lib/experimental/script-modules.php index 60460bc3698d6..202fd63a3d0d0 100644 --- a/lib/experimental/script-modules.php +++ b/lib/experimental/script-modules.php @@ -200,7 +200,15 @@ function gutenberg_dequeue_module( $module_identifier ) { /** - * @since 18.4.0 + * Print data associated with Script Modules in Script tags. + * + * This embeds data in the page HTML so that it is available on page load. + * + * Data can be associated with a given Script Module by using the + * `scriptmoduledata_{$module_id}` filter. + * + * The data for a given Script Module will be JSON serialized in a script tag with an ID + * like `wp-scriptmodule-data_{$module_id}`. */ function gutenberg_print_script_module_data(): void { $get_marked_for_enqueue = new ReflectionMethod( 'WP_Script_Modules', 'get_marked_for_enqueue' ); @@ -215,7 +223,26 @@ function gutenberg_print_script_module_data(): void { } foreach ( array_keys( $modules ) as $module_id ) { + /** + * Filters data associated with a given Script Module. + * + * Script Modules may require data that is required for initialization or is essential to + * have immediately available on page load. These are suitable use cases for this data. + * + * This is best suited to a minimal set of data and is not intended to replace the REST API. + * + * If the filter returns no data (an empty array), nothing will be embedded in the page. + * + * The data for a given Script Module, if provided, will be JSON serialized in a script tag + * with an ID like `wp-scriptmodule-data_{$module_id}`. + * + * The dynamic portion of the hook name, `$module_id`, refers to the Script Module ID that + * the data is associated with. + * + * @param array $data The data that should be associated with the array. + */ $data = apply_filters( "scriptmoduledata_{$module_id}", array() ); + if ( ! empty( $data ) ) { /* * This data will be printed as JSON inside a script tag like this: @@ -264,7 +291,7 @@ function gutenberg_print_script_module_data(): void { wp_json_encode( $data, $json_encode_flags ), array( 'type' => 'application/json', - 'id' => 'wp-scriptmodule-data_' . $module_id, + 'id' => "wp-scriptmodule-data_{$module_id}", ) ); } From 89d3a8abf5e9cc0f6c2dc06f59dc318fe2783175 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Wed, 15 May 2024 13:16:31 +0200 Subject: [PATCH 09/12] Update JSON flags and comments Aligns with https://github.com/WordPress/wordpress-develop/pull/6520 --- lib/experimental/script-modules.php | 44 +++++++++++------------------ 1 file changed, 16 insertions(+), 28 deletions(-) diff --git a/lib/experimental/script-modules.php b/lib/experimental/script-modules.php index 202fd63a3d0d0..b514e6f16b0ca 100644 --- a/lib/experimental/script-modules.php +++ b/lib/experimental/script-modules.php @@ -255,36 +255,24 @@ function gutenberg_print_script_module_data(): void { * - JSON_HEX_TAG: All < and > are converted to \u003C and \u003E. * - JSON_UNESCAPED_SLASHES: Don't escape /. * + * If the page will use UTF-8 encoding, it's safe to print unescaped unicode: + * + * - JSON_UNESCAPED_UNICODE: Encode multibyte Unicode characters literally (instead of as `\uXXXX`). + * - JSON_UNESCAPED_LINE_TERMINATORS: The line terminators are kept unescaped when + * JSON_UNESCAPED_UNICODE is supplied. It uses the same behaviour as it was + * before PHP 7.1 without this constant. Available as of PHP 7.1.0. + * + * The JSON specification requires encoding in UTF-8, so if the generated HTML page + * is not encoded in UTF-8 then it's not safe to include those literals. They must + * be escaped to avoid encoding issues. + * + * @see https://www.rfc-editor.org/rfc/rfc8259.html for details on encoding requirements. * @see https://www.php.net/manual/en/json.constants.php for details on these constants. - * @see https://html.spec.whatwg.org/#script-data-state for details on script - * tag parsing. + * @see https://html.spec.whatwg.org/#script-data-state for details on script tag parsing. */ - $json_encode_flags = JSON_HEX_TAG | JSON_UNESCAPED_SLASHES; - if ( 'UTF-8' === get_option( 'blog_charset' ) ) { - /* - * If the page will use UTF-8 encoding, it's safe to print unescaped unicode in - * JSON. Set the following flags: - * - * - JSON_UNESCAPED_UNICODE: Encode multibyte Unicode characters literally - * (default is to escape as \uXXXX). - * - JSON_UNESCAPED_LINE_TERMINATORS: The line terminators are kept unescaped when - * JSON_UNESCAPED_UNICODE is supplied. It uses the same behaviour as it was - * before PHP 7.1 without this constant. Available as of PHP 7.1.0. - * - * The JSON specification does not specify a character encoding, RFC-8259 - * suggests that UTF-8 be used everywhere. It's risky to print unicode if the page - * uses any other encoding. - * - * > JSON text exchanged between systems that are not part of a closed ecosystem - * > MUST be encoded using UTF-8. Previous specifications of JSON have not required - * > the use of UTF-8 when transmitting JSON text. However, the vast majority of - * > JSON- based software implementations have chosen to use the UTF-8 encoding, - * > to the extent that it is the only encoding that achieves interoperability. - * - * @see https://www.rfc-editor.org/rfc/rfc8259.html - * - */ - $json_encode_flags |= JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_LINE_TERMINATORS; + $json_encode_flags = JSON_HEX_TAG | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_LINE_TERMINATORS; + if ( 'UTF-8' !== get_option( 'blog_charset' ) ) { + $json_encode_flags = JSON_HEX_TAG | JSON_UNESCAPED_SLASHES; } wp_print_inline_script_tag( From 2b1e5317e5f5e62c7c555556d07754ea6c30453f Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Wed, 15 May 2024 13:20:35 +0200 Subject: [PATCH 10/12] Properly use the filter for interactivity data --- .../class-wp-interactivity-api.php | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/lib/compat/wordpress-6.5/interactivity-api/class-wp-interactivity-api.php b/lib/compat/wordpress-6.5/interactivity-api/class-wp-interactivity-api.php index 0e350487f9b86..5adb9a29edd59 100644 --- a/lib/compat/wordpress-6.5/interactivity-api/class-wp-interactivity-api.php +++ b/lib/compat/wordpress-6.5/interactivity-api/class-wp-interactivity-api.php @@ -131,22 +131,21 @@ public function config( string $store_namespace, array $config = array() ): arra } /** - * Prints the serialized client-side interactivity data. + * Adds interactivity data to filtered data to be passed to the client. * - * Encodes the config and initial state into JSON and prints them inside a - * script tag of type "application/json". Once in the browser, the state will - * be parsed and used to hydrate the client-side interactivity stores and the - * configuration will be available using a `getConfig` utility. + * Once in the browser, the state will be parsed and used to hydrate the client-side + * interactivity stores and the configuration will be available using a `getConfig` utility. * * @since 6.5.0 + * + * @param array $interactivity_data Interactivity data. + * @return array $interactivity_data Interactivity data with store data added (if it exists). */ - public function print_client_interactivity_data() { + public function print_client_interactivity_data( $interactivity_data ) { if ( empty( $this->state_data ) && empty( $this->config_data ) ) { - return; + return $interactivity_data; } - $interactivity_data = array(); - $config = array(); foreach ( $this->config_data as $key => $value ) { if ( ! empty( $value ) ) { From becb1884b4a141fdc44887db184351b19f692e53 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Thu, 30 May 2024 13:13:26 +0200 Subject: [PATCH 11/12] Add is_array check before printing data --- lib/experimental/script-modules.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/experimental/script-modules.php b/lib/experimental/script-modules.php index b514e6f16b0ca..7ca14e43d715b 100644 --- a/lib/experimental/script-modules.php +++ b/lib/experimental/script-modules.php @@ -243,7 +243,7 @@ function gutenberg_print_script_module_data(): void { */ $data = apply_filters( "scriptmoduledata_{$module_id}", array() ); - if ( ! empty( $data ) ) { + if ( is_array( $data ) && ! empty( $data ) ) { /* * This data will be printed as JSON inside a script tag like this: * From f6a78396c8485b3895f2207cdb90d2e7c9aabae5 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Thu, 30 May 2024 15:00:54 +0200 Subject: [PATCH 12/12] Revert Interactivity API script printing changes These demonstrate that the proposed changes work and are adequate for Interactivity API, but change a public function signature and implementation. --- .../class-wp-interactivity-api.php | 32 +++++++++++++------ 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/lib/compat/wordpress-6.5/interactivity-api/class-wp-interactivity-api.php b/lib/compat/wordpress-6.5/interactivity-api/class-wp-interactivity-api.php index 5adb9a29edd59..d0661d7585726 100644 --- a/lib/compat/wordpress-6.5/interactivity-api/class-wp-interactivity-api.php +++ b/lib/compat/wordpress-6.5/interactivity-api/class-wp-interactivity-api.php @@ -131,21 +131,22 @@ public function config( string $store_namespace, array $config = array() ): arra } /** - * Adds interactivity data to filtered data to be passed to the client. + * Prints the serialized client-side interactivity data. * - * Once in the browser, the state will be parsed and used to hydrate the client-side - * interactivity stores and the configuration will be available using a `getConfig` utility. + * Encodes the config and initial state into JSON and prints them inside a + * script tag of type "application/json". Once in the browser, the state will + * be parsed and used to hydrate the client-side interactivity stores and the + * configuration will be available using a `getConfig` utility. * * @since 6.5.0 - * - * @param array $interactivity_data Interactivity data. - * @return array $interactivity_data Interactivity data with store data added (if it exists). */ - public function print_client_interactivity_data( $interactivity_data ) { + public function print_client_interactivity_data() { if ( empty( $this->state_data ) && empty( $this->config_data ) ) { - return $interactivity_data; + return; } + $interactivity_data = array(); + $config = array(); foreach ( $this->config_data as $key => $value ) { if ( ! empty( $value ) ) { @@ -166,7 +167,18 @@ public function print_client_interactivity_data( $interactivity_data ) { $interactivity_data['state'] = $state; } - return $interactivity_data; + if ( ! empty( $interactivity_data ) ) { + wp_print_inline_script_tag( + wp_json_encode( + $interactivity_data, + JSON_HEX_TAG | JSON_HEX_AMP + ), + array( + 'type' => 'application/json', + 'id' => 'wp-interactivity-data', + ) + ); + } } /** @@ -196,7 +208,7 @@ public function register_script_modules() { */ public function add_hooks() { add_action( 'wp_enqueue_scripts', array( $this, 'register_script_modules' ) ); - add_filter( 'scriptmoduledata_@wordpress/interactivity', array( $this, 'print_client_interactivity_data' ) ); + add_action( 'wp_footer', array( $this, 'print_client_interactivity_data' ) ); } /**