@@ -634,23 +634,6 @@ public function localize( $handle, $object_name, $l10n ) {
634634 }
635635 }
636636
637- /**
638- * Filters data associated with a given script.
639- *
640- * The dynamic portion of the hook name, `$handle`, refers to the script handle.
641- *
642- * This filter allows developers to modify the data passed to a script via
643- * wp_localize_script() before it is output. This is analogous to the
644- * `script_module_data_{$module_id}` filter for script modules.
645- *
646- * @since 6.8.0
647- *
648- * @param array|string $l10n The data to be localized.
649- * @param string $object_name The JavaScript object name.
650- * @param string $handle The script handle.
651- */
652- $ l10n = apply_filters ( "script_data_ {$ handle }" , $ l10n , $ object_name , $ handle );
653-
654637 $ script = "var $ object_name = " . wp_json_encode ( $ l10n , JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ) . '; ' ;
655638
656639 if ( ! empty ( $ after ) ) {
@@ -1199,4 +1182,120 @@ protected function get_dependency_warning_message( $handle, $missing_dependency_
11991182 implode ( ', ' , $ missing_dependency_handles )
12001183 );
12011184 }
1185+
1186+ /**
1187+ * Prints data associated with scripts.
1188+ *
1189+ * The data will be embedded in the page HTML and can be read by scripts on page load.
1190+ *
1191+ * Data can be associated with a script via the {@see "script_data_{$handle}"} filter.
1192+ *
1193+ * The data for a script will be serialized as JSON in a script tag with an ID of the
1194+ * form `wp-script-data-{$handle}`.
1195+ *
1196+ * @since 6.8.0
1197+ */
1198+ public function print_script_data () {
1199+ $ scripts = array ();
1200+
1201+ // Collect all enqueued scripts and their dependencies.
1202+ foreach ( array_unique ( $ this ->queue ) as $ handle ) {
1203+ $ scripts [ $ handle ] = true ;
1204+ }
1205+
1206+ foreach ( array_keys ( $ scripts ) as $ handle ) {
1207+ /**
1208+ * Filters data associated with a given script.
1209+ *
1210+ * The dynamic portion of the hook name, `$handle`, refers to the script handle.
1211+ *
1212+ * Scripts may require data that is required for initialization or is essential
1213+ * to have immediately available on page load. These are suitable use cases for
1214+ * this data.
1215+ *
1216+ * This is best suited to pass essential data that must be available to the script for
1217+ * initialization or immediately on page load. It does not replace the REST API or
1218+ * fetching data from the client.
1219+ *
1220+ * Example:
1221+ *
1222+ * add_filter(
1223+ * 'script_data_my-script-handle',
1224+ * function ( array $data ): array {
1225+ * $data['myData'] = array(
1226+ * 'option' => get_option( 'my_option' ),
1227+ * );
1228+ * return $data;
1229+ * }
1230+ * );
1231+ *
1232+ * If the filter returns no data (an empty array), nothing will be embedded in the page.
1233+ *
1234+ * The data for a given script, if provided, will be JSON serialized in a script
1235+ * tag with an ID of the form `wp-script-data-{$handle}`.
1236+ *
1237+ * The data can be read on the client with a pattern like this:
1238+ *
1239+ * Example:
1240+ *
1241+ * const dataContainer = document.getElementById( 'wp-script-data-my-script-handle' );
1242+ * let data = {};
1243+ * if ( dataContainer ) {
1244+ * try {
1245+ * data = JSON.parse( dataContainer.textContent );
1246+ * } catch {}
1247+ * }
1248+ * initMyScriptWithData( data );
1249+ *
1250+ * @since 6.8.0
1251+ *
1252+ * @param array $data The data associated with the script.
1253+ */
1254+ $ data = apply_filters ( "script_data_ {$ handle }" , array () );
1255+
1256+ if ( is_array ( $ data ) && array () !== $ data ) {
1257+ /*
1258+ * This data will be printed as JSON inside a script tag like this:
1259+ * <script type="application/json"></script>
1260+ *
1261+ * A script tag must be closed by a sequence beginning with `</`. It's impossible to
1262+ * close a script tag without using `<`. We ensure that `<` is escaped and `/` can
1263+ * remain unescaped, so `</script>` will be printed as `\u003C/script>`.
1264+ *
1265+ * - JSON_HEX_TAG: All < and > are converted to \u003C and \u003E.
1266+ * - JSON_UNESCAPED_SLASHES: Don't escape /.
1267+ *
1268+ * If the page will use UTF-8 encoding, it's safe to print unescaped unicode:
1269+ *
1270+ * - JSON_UNESCAPED_UNICODE: Encode multibyte Unicode characters literally (instead of as `\uXXXX`).
1271+ * - JSON_UNESCAPED_LINE_TERMINATORS: The line terminators are kept unescaped when
1272+ * JSON_UNESCAPED_UNICODE is supplied. It uses the same behaviour as it was
1273+ * before PHP 7.1 without this constant. Available as of PHP 7.1.0.
1274+ *
1275+ * The JSON specification requires encoding in UTF-8, so if the generated HTML page
1276+ * is not encoded in UTF-8 then it's not safe to include those literals. They must
1277+ * be escaped to avoid encoding issues.
1278+ *
1279+ * @see https://www.rfc-editor.org/rfc/rfc8259.html for details on encoding requirements.
1280+ * @see https://www.php.net/manual/en/json.constants.php for details on these constants.
1281+ * @see https://html.spec.whatwg.org/#script-data-state for details on script tag parsing.
1282+ */
1283+ $ json_encode_flags = JSON_HEX_TAG | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_LINE_TERMINATORS ;
1284+ if ( ! is_utf8_charset () ) {
1285+ $ json_encode_flags = JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ;
1286+ }
1287+
1288+ wp_print_inline_script_tag (
1289+ (string ) wp_json_encode (
1290+ $ data ,
1291+ $ json_encode_flags
1292+ ),
1293+ array (
1294+ 'type ' => 'application/json ' ,
1295+ 'id ' => "wp-script-data- {$ handle }" ,
1296+ )
1297+ );
1298+ }
1299+ }
1300+ }
12021301}
0 commit comments