From 00a87fafdd05d3b0db5f87b6e57de0e30e8fe02a Mon Sep 17 00:00:00 2001 From: George Mamadashvili Date: Wed, 23 Feb 2022 12:59:22 +0400 Subject: [PATCH 1/7] Override REST API route --- ...-gutenberg-rest-edit-site-export-controller.php} | 5 +++-- lib/compat/wordpress-6.0/rest-api.php | 13 ++++++++++++- lib/load.php | 5 +---- lib/rest-api.php | 11 ----------- 4 files changed, 16 insertions(+), 18 deletions(-) rename lib/compat/{wordpress-5.9/class-wp-rest-edit-site-export-controller.php => wordpress-6.0/class-gutenberg-rest-edit-site-export-controller.php} (93%) diff --git a/lib/compat/wordpress-5.9/class-wp-rest-edit-site-export-controller.php b/lib/compat/wordpress-6.0/class-gutenberg-rest-edit-site-export-controller.php similarity index 93% rename from lib/compat/wordpress-5.9/class-wp-rest-edit-site-export-controller.php rename to lib/compat/wordpress-6.0/class-gutenberg-rest-edit-site-export-controller.php index d8895ba067463..8a3562551c084 100644 --- a/lib/compat/wordpress-5.9/class-wp-rest-edit-site-export-controller.php +++ b/lib/compat/wordpress-6.0/class-gutenberg-rest-edit-site-export-controller.php @@ -14,7 +14,7 @@ * * @see WP_REST_Controller */ -class WP_REST_Edit_Site_Export_Controller extends WP_REST_Controller { +class Gutenberg_REST_Edit_Site_Export_Controller extends WP_REST_Controller { /** * Constructs the controller. @@ -37,7 +37,8 @@ public function register_routes() { 'callback' => array( $this, 'export' ), 'permission_callback' => array( $this, 'permissions_check' ), ), - ) + ), + true, // Override core route if already exists (WP 5.9). ); } diff --git a/lib/compat/wordpress-6.0/rest-api.php b/lib/compat/wordpress-6.0/rest-api.php index 8ccbf4f35b0b0..da1f6977e73ca 100644 --- a/lib/compat/wordpress-6.0/rest-api.php +++ b/lib/compat/wordpress-6.0/rest-api.php @@ -22,4 +22,15 @@ function gutenberg_register_rest_pattern_directory() { $pattern_directory_controller = new Gutenberg_REST_Pattern_Directory_Controller(); $pattern_directory_controller->register_routes(); } -add_filter( 'rest_api_init', 'gutenberg_register_rest_pattern_directory' ); +add_action( 'rest_api_init', 'gutenberg_register_rest_pattern_directory' ); + +/** + * Registers the Edit Site's Export REST API routes. + * + * @return void + */ +function gutenberg_register_edit_site_export_endpoint() { + $editor_settings = new Gutenberg_REST_Edit_Site_Export_Controller(); + $editor_settings->register_routes(); +} +add_action( 'rest_api_init', 'gutenberg_register_edit_site_export_endpoint' ); diff --git a/lib/load.php b/lib/load.php index 443942c98ee80..1b2d55024ee50 100644 --- a/lib/load.php +++ b/lib/load.php @@ -55,10 +55,6 @@ function gutenberg_is_experiment_enabled( $name ) { require_once __DIR__ . '/class-wp-rest-url-details-controller.php'; } - if ( ! class_exists( 'WP_REST_Edit_Site_Export_Controller' ) ) { - require_once __DIR__ . '/compat/wordpress-5.9/class-wp-rest-edit-site-export-controller.php'; - } - require __DIR__ . '/rest-api.php'; } @@ -96,6 +92,7 @@ function gutenberg_is_experiment_enabled( $name ) { require __DIR__ . '/compat/wordpress-6.0/blocks.php'; require __DIR__ . '/compat/wordpress-6.0/class-gutenberg-rest-global-styles-controller.php'; require __DIR__ . '/compat/wordpress-6.0/class-gutenberg-rest-pattern-directory-controller.php'; +require __DIR__ . '/compat/wordpress-6.0/class-gutenberg-rest-edit-site-export-controller.php'; require __DIR__ . '/compat/wordpress-6.0/class-wp-theme-json-gutenberg.php'; require __DIR__ . '/compat/wordpress-6.0/rest-api.php'; require __DIR__ . '/compat/wordpress-6.0/block-patterns.php'; diff --git a/lib/rest-api.php b/lib/rest-api.php index 9fef898eb6d60..a28d23e6912e2 100644 --- a/lib/rest-api.php +++ b/lib/rest-api.php @@ -209,14 +209,3 @@ function gutenberg_rest_user_collection_params_has_published_posts( $query_param return $query_params; } add_filter( 'rest_user_collection_params', 'gutenberg_rest_user_collection_params_has_published_posts' ); - -/** - * Registers the Edit Site's Export REST API routes. - * - * @return void - */ -function gutenberg_register_edit_site_export_endpoint() { - $editor_settings = new WP_REST_Edit_Site_Export_Controller(); - $editor_settings->register_routes(); -} -add_action( 'rest_api_init', 'gutenberg_register_edit_site_export_endpoint' ); From 0b5dfc9efb7792b380fc2c0f99a3081b9e4714ec Mon Sep 17 00:00:00 2001 From: George Mamadashvili Date: Wed, 23 Feb 2022 13:46:20 +0400 Subject: [PATCH 2/7] Port changes from previous PR --- .../wordpress-5.9/block-template-utils.php | 54 --------------- .../wordpress-6.0/block-template-utils.php | 69 +++++++++++++++++++ ...nberg-rest-edit-site-export-controller.php | 4 +- lib/load.php | 1 + 4 files changed, 72 insertions(+), 56 deletions(-) create mode 100644 lib/compat/wordpress-6.0/block-template-utils.php diff --git a/lib/compat/wordpress-5.9/block-template-utils.php b/lib/compat/wordpress-5.9/block-template-utils.php index 70cc03152c792..0b41907d7a931 100644 --- a/lib/compat/wordpress-5.9/block-template-utils.php +++ b/lib/compat/wordpress-5.9/block-template-utils.php @@ -894,57 +894,3 @@ function block_footer_area() { block_template_part( 'footer' ); } } - -if ( ! function_exists( 'wp_generate_block_templates_export_file' ) ) { - /** - * Creates an export of the current templates and - * template parts from the site editor at the - * specified path in a ZIP file. - * - * @since 5.9.0 - * - * @return WP_Error|string Path of the ZIP file or error on failure. - */ - function wp_generate_block_templates_export_file() { - if ( ! class_exists( 'ZipArchive' ) ) { - return new WP_Error( 'missing_zip_package', __( 'Zip Export not supported.', 'gutenberg' ) ); - } - - $obscura = wp_generate_password( 12, false, false ); - $filename = get_temp_dir() . 'edit-site-export-' . $obscura . '.zip'; - - $zip = new ZipArchive(); - if ( true !== $zip->open( $filename, ZipArchive::CREATE ) ) { - return new WP_Error( 'unable_to_create_zip', __( 'Unable to open export file (archive) for writing.', 'gutenberg' ) ); - } - - $zip->addEmptyDir( 'theme' ); - $zip->addEmptyDir( 'theme/templates' ); - $zip->addEmptyDir( 'theme/parts' ); - - // Load templates into the zip file. - $templates = gutenberg_get_block_templates(); - foreach ( $templates as $template ) { - $template->content = _remove_theme_attribute_in_block_template_content( $template->content ); - - $zip->addFromString( - 'theme/templates/' . $template->slug . '.html', - $template->content - ); - } - - // Load template parts into the zip file. - $template_parts = gutenberg_get_block_templates( array(), 'wp_template_part' ); - foreach ( $template_parts as $template_part ) { - $zip->addFromString( - 'theme/parts/' . $template_part->slug . '.html', - $template_part->content - ); - } - - // Save changes to the zip file. - $zip->close(); - - return $filename; - } -} diff --git a/lib/compat/wordpress-6.0/block-template-utils.php b/lib/compat/wordpress-6.0/block-template-utils.php new file mode 100644 index 0000000000000..b8de35328c832 --- /dev/null +++ b/lib/compat/wordpress-6.0/block-template-utils.php @@ -0,0 +1,69 @@ +open( $filename, ZipArchive::CREATE ) ) { + return new WP_Error( 'unable_to_create_zip', __( 'Unable to open export file (archive) for writing.', 'gutenberg' ) ); + } + + $zip->addEmptyDir( 'theme' ); + $zip->addEmptyDir( 'theme/templates' ); + $zip->addEmptyDir( 'theme/parts' ); + + // Load templates into the zip file. + $templates = gutenberg_get_block_templates(); + foreach ( $templates as $template ) { + $template->content = _remove_theme_attribute_in_block_template_content( $template->content ); + + $zip->addFromString( + 'theme/templates/' . $template->slug . '.html', + $template->content + ); + } + + // Load template parts into the zip file. + $template_parts = gutenberg_get_block_templates( array(), 'wp_template_part' ); + foreach ( $template_parts as $template_part ) { + $zip->addFromString( + 'theme/parts/' . $template_part->slug . '.html', + $template_part->content + ); + } + + $tree = WP_Theme_JSON_Resolver_Gutenberg::get_theme_data(); + $tree->merge( WP_Theme_JSON_Resolver_Gutenberg::get_user_data() ); + + $zip->addFromString( + 'theme/theme.json', + wp_json_encode( $tree->get_raw_data(), JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE ) + ); + + // Save changes to the zip file. + $zip->close(); + + return $filename; +} diff --git a/lib/compat/wordpress-6.0/class-gutenberg-rest-edit-site-export-controller.php b/lib/compat/wordpress-6.0/class-gutenberg-rest-edit-site-export-controller.php index 8a3562551c084..59cde2a883494 100644 --- a/lib/compat/wordpress-6.0/class-gutenberg-rest-edit-site-export-controller.php +++ b/lib/compat/wordpress-6.0/class-gutenberg-rest-edit-site-export-controller.php @@ -38,7 +38,7 @@ public function register_routes() { 'permission_callback' => array( $this, 'permissions_check' ), ), ), - true, // Override core route if already exists (WP 5.9). + true // Override core route if already exists (WP 5.9). ); } @@ -67,7 +67,7 @@ public function permissions_check() { */ public function export() { // Generate the export file. - $filename = wp_generate_block_templates_export_file(); + $filename = gutenberg_generate_block_templates_export_file(); if ( is_wp_error( $filename ) ) { $filename->add_data( array( 'status' => 500 ) ); diff --git a/lib/load.php b/lib/load.php index 1b2d55024ee50..40d65b4fe97b9 100644 --- a/lib/load.php +++ b/lib/load.php @@ -90,6 +90,7 @@ function gutenberg_is_experiment_enabled( $name ) { require __DIR__ . '/compat/wordpress-5.9/move-theme-editor-menu-item.php'; require __DIR__ . '/compat/wordpress-6.0/post-lock.php'; require __DIR__ . '/compat/wordpress-6.0/blocks.php'; +require __DIR__ . '/compat/wordpress-6.0/block-template-utils.php'; require __DIR__ . '/compat/wordpress-6.0/class-gutenberg-rest-global-styles-controller.php'; require __DIR__ . '/compat/wordpress-6.0/class-gutenberg-rest-pattern-directory-controller.php'; require __DIR__ . '/compat/wordpress-6.0/class-gutenberg-rest-edit-site-export-controller.php'; From 1272c5dd39acdea906549bdd14da7d684153f5b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Fri, 25 Feb 2022 12:50:20 +0100 Subject: [PATCH 3/7] Add export_theme_json method --- .../class-wp-theme-json-gutenberg.php | 42 +++++ phpunit/class-wp-theme-json-test.php | 170 ++++++++++++++++++ 2 files changed, 212 insertions(+) diff --git a/lib/compat/wordpress-6.0/class-wp-theme-json-gutenberg.php b/lib/compat/wordpress-6.0/class-wp-theme-json-gutenberg.php index a78e89e397604..261ffea0f84de 100644 --- a/lib/compat/wordpress-6.0/class-wp-theme-json-gutenberg.php +++ b/lib/compat/wordpress-6.0/class-wp-theme-json-gutenberg.php @@ -42,4 +42,46 @@ public function get_patterns() { } return array(); } + + /** + * Returns a valid theme.json for a theme. + * Essentially, it flattens the preset data. + * + * @return array + */ + public function export_theme_json() { + $flattened_theme_json = $this->theme_json; + $nodes = static::get_setting_nodes( $this->theme_json ); + foreach ( $nodes as $node ) { + foreach ( static::PRESETS_METADATA as $preset_metadata ) { + $path = array_merge( $node['path'], $preset_metadata['path'] ); + $preset = _wp_array_get( $flattened_theme_json, $path, null ); + if ( null !== $preset ) { + $items = array(); + if ( isset( $preset['theme'] ) ) { + foreach ( $preset['theme'] as $item ) { + $slug = $item['slug']; + unset( $item['slug'] ); + $items[ $slug ] = $item; + } + } + if ( isset( $preset['custom'] ) ) { + foreach ( $preset['custom'] as $item ) { + $slug = $item['slug']; + unset( $item['slug'] ); + $items[ $slug ] = $item; + } + } + $flattened_preset = array(); + foreach ( $items as $slug => $value ) { + $flattened_preset[] = array_merge( array( 'slug' => $slug ), $value ); + } + _wp_array_set( $flattened_theme_json, $path, $flattened_preset ); + } + } + } + + return $flattened_theme_json; + } + } diff --git a/phpunit/class-wp-theme-json-test.php b/phpunit/class-wp-theme-json-test.php index ea7c967556041..9d580f3601953 100644 --- a/phpunit/class-wp-theme-json-test.php +++ b/phpunit/class-wp-theme-json-test.php @@ -2281,4 +2281,174 @@ function test_sanitization() { $this->assertEqualSetsWithIndex( $expected, $actual ); } + function test_export_data() { + $theme = new WP_Theme_JSON_Gutenberg( + array( + 'version' => 2, + 'settings' => array( + 'color' => array( + 'palette' => array( + array( + 'slug' => 'white', + 'color' => 'white', + 'label' => 'White', + ), + array( + 'slug' => 'black', + 'color' => 'black', + 'label' => 'Black', + ), + ), + ), + ), + ) + ); + $user = new WP_Theme_JSON_Gutenberg( + array( + 'version' => 2, + 'settings' => array( + 'color' => array( + 'palette' => array( + array( + 'slug' => 'white', + 'color' => '#fff', + 'label' => 'User White', + ), + array( + 'slug' => 'hotpink', + 'color' => 'hotpink', + 'label' => 'hotpink', + ), + ), + ), + ), + ), + 'custom' + ); + + $theme->merge( $user ); + $actual = $theme->export_theme_json(); + $expected = array( + 'version' => 2, + 'settings' => array( + 'color' => array( + 'palette' => array( + array( + 'slug' => 'white', + 'color' => '#fff', + 'label' => 'User White', + ), + array( + 'slug' => 'black', + 'color' => 'black', + 'label' => 'Black', + ), + array( + 'slug' => 'hotpink', + 'color' => 'hotpink', + 'label' => 'hotpink', + ), + ), + ), + ), + ); + + $this->assertEqualSetsWithIndex( $expected, $actual ); + } + + function test_export_data_deals_with_empty_user_data() { + $theme = new WP_Theme_JSON_Gutenberg( + array( + 'version' => 2, + 'settings' => array( + 'color' => array( + 'palette' => array( + array( + 'slug' => 'white', + 'color' => 'white', + 'label' => 'White', + ), + array( + 'slug' => 'black', + 'color' => 'black', + 'label' => 'Black', + ), + ), + ), + ), + ) + ); + + $actual = $theme->export_theme_json(); + $expected = array( + 'version' => 2, + 'settings' => array( + 'color' => array( + 'palette' => array( + array( + 'slug' => 'white', + 'color' => 'white', + 'label' => 'White', + ), + array( + 'slug' => 'black', + 'color' => 'black', + 'label' => 'Black', + ), + ), + ), + ), + ); + + $this->assertEqualSetsWithIndex( $expected, $actual ); + } + + function test_export_data_deals_with_empty_theme_data() { + $user = new WP_Theme_JSON_Gutenberg( + array( + 'version' => 2, + 'settings' => array( + 'color' => array( + 'palette' => array( + array( + 'slug' => 'white', + 'color' => '#fff', + 'label' => 'User White', + ), + array( + 'slug' => 'hotpink', + 'color' => 'hotpink', + 'label' => 'hotpink', + ), + ), + ), + ), + ), + 'custom' + ); + + $actual = $user->export_theme_json(); + $expected = array( + 'version' => 2, + 'settings' => array( + 'color' => array( + 'palette' => array( + array( + 'slug' => 'white', + 'color' => '#fff', + 'label' => 'User White', + ), + array( + 'slug' => 'hotpink', + 'color' => 'hotpink', + 'label' => 'hotpink', + ), + ), + ), + ), + ); + + $this->assertEqualSetsWithIndex( $expected, $actual ); + } + } From ea5750b5198f24b537c2a189caaab506204bb61e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Fri, 25 Feb 2022 12:51:54 +0100 Subject: [PATCH 4/7] Use new method to get exported data --- lib/compat/wordpress-6.0/block-template-utils.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/compat/wordpress-6.0/block-template-utils.php b/lib/compat/wordpress-6.0/block-template-utils.php index b8de35328c832..74bc6ed8e0a60 100644 --- a/lib/compat/wordpress-6.0/block-template-utils.php +++ b/lib/compat/wordpress-6.0/block-template-utils.php @@ -59,7 +59,7 @@ function gutenberg_generate_block_templates_export_file() { $zip->addFromString( 'theme/theme.json', - wp_json_encode( $tree->get_raw_data(), JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE ) + wp_json_encode( $tree->export_theme_json(), JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE ) ); // Save changes to the zip file. From 5a64ea43b290b8ee41bdf0d263fe2ae439729467 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Fri, 25 Feb 2022 14:06:04 +0100 Subject: [PATCH 5/7] Rename export_theme_json to get_data --- lib/compat/wordpress-6.0/block-template-utils.php | 2 +- lib/compat/wordpress-6.0/class-wp-theme-json-gutenberg.php | 2 +- phpunit/class-wp-theme-json-test.php | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/compat/wordpress-6.0/block-template-utils.php b/lib/compat/wordpress-6.0/block-template-utils.php index 74bc6ed8e0a60..f3f3f32ff5aa0 100644 --- a/lib/compat/wordpress-6.0/block-template-utils.php +++ b/lib/compat/wordpress-6.0/block-template-utils.php @@ -59,7 +59,7 @@ function gutenberg_generate_block_templates_export_file() { $zip->addFromString( 'theme/theme.json', - wp_json_encode( $tree->export_theme_json(), JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE ) + wp_json_encode( $tree->get_data(), JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE ) ); // Save changes to the zip file. diff --git a/lib/compat/wordpress-6.0/class-wp-theme-json-gutenberg.php b/lib/compat/wordpress-6.0/class-wp-theme-json-gutenberg.php index 261ffea0f84de..a8fed0798158b 100644 --- a/lib/compat/wordpress-6.0/class-wp-theme-json-gutenberg.php +++ b/lib/compat/wordpress-6.0/class-wp-theme-json-gutenberg.php @@ -49,7 +49,7 @@ public function get_patterns() { * * @return array */ - public function export_theme_json() { + public function get_data() { $flattened_theme_json = $this->theme_json; $nodes = static::get_setting_nodes( $this->theme_json ); foreach ( $nodes as $node ) { diff --git a/phpunit/class-wp-theme-json-test.php b/phpunit/class-wp-theme-json-test.php index 9d580f3601953..09f875fb3b7a0 100644 --- a/phpunit/class-wp-theme-json-test.php +++ b/phpunit/class-wp-theme-json-test.php @@ -2327,7 +2327,7 @@ function test_export_data() { ); $theme->merge( $user ); - $actual = $theme->export_theme_json(); + $actual = $theme->get_data(); $expected = array( 'version' => 2, 'settings' => array( @@ -2379,7 +2379,7 @@ function test_export_data_deals_with_empty_user_data() { ) ); - $actual = $theme->export_theme_json(); + $actual = $theme->get_data(); $expected = array( 'version' => 2, 'settings' => array( @@ -2427,7 +2427,7 @@ function test_export_data_deals_with_empty_theme_data() { 'custom' ); - $actual = $user->export_theme_json(); + $actual = $user->get_data(); $expected = array( 'version' => 2, 'settings' => array( From 7f4f48d3261ae7ee258d1c4a85fe28dd78fc7fba Mon Sep 17 00:00:00 2001 From: George Mamadashvili Date: Tue, 1 Mar 2022 12:55:42 +0400 Subject: [PATCH 6/7] Improve nesting --- .../class-wp-theme-json-gutenberg.php | 40 ++++++++++--------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/lib/compat/wordpress-6.0/class-wp-theme-json-gutenberg.php b/lib/compat/wordpress-6.0/class-wp-theme-json-gutenberg.php index a8fed0798158b..c68f6fb3d205a 100644 --- a/lib/compat/wordpress-6.0/class-wp-theme-json-gutenberg.php +++ b/lib/compat/wordpress-6.0/class-wp-theme-json-gutenberg.php @@ -56,28 +56,30 @@ public function get_data() { foreach ( static::PRESETS_METADATA as $preset_metadata ) { $path = array_merge( $node['path'], $preset_metadata['path'] ); $preset = _wp_array_get( $flattened_theme_json, $path, null ); - if ( null !== $preset ) { - $items = array(); - if ( isset( $preset['theme'] ) ) { - foreach ( $preset['theme'] as $item ) { - $slug = $item['slug']; - unset( $item['slug'] ); - $items[ $slug ] = $item; - } - } - if ( isset( $preset['custom'] ) ) { - foreach ( $preset['custom'] as $item ) { - $slug = $item['slug']; - unset( $item['slug'] ); - $items[ $slug ] = $item; - } + if ( null === $preset ) { + continue; + } + + $items = array(); + if ( isset( $preset['theme'] ) ) { + foreach ( $preset['theme'] as $item ) { + $slug = $item['slug']; + unset( $item['slug'] ); + $items[ $slug ] = $item; } - $flattened_preset = array(); - foreach ( $items as $slug => $value ) { - $flattened_preset[] = array_merge( array( 'slug' => $slug ), $value ); + } + if ( isset( $preset['custom'] ) ) { + foreach ( $preset['custom'] as $item ) { + $slug = $item['slug']; + unset( $item['slug'] ); + $items[ $slug ] = $item; } - _wp_array_set( $flattened_theme_json, $path, $flattened_preset ); } + $flattened_preset = array(); + foreach ( $items as $slug => $value ) { + $flattened_preset[] = array_merge( array( 'slug' => $slug ), $value ); + } + _wp_array_set( $flattened_theme_json, $path, $flattened_preset ); } } From ab90a56b06a773eb76cd85020644da39d4d04b24 Mon Sep 17 00:00:00 2001 From: Ben Dwyer Date: Wed, 2 Mar 2022 11:36:49 +0000 Subject: [PATCH 7/7] Update the export label --- .../edit-site/src/components/header/more-menu/site-export.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/edit-site/src/components/header/more-menu/site-export.js b/packages/edit-site/src/components/header/more-menu/site-export.js index fbbd1097c4379..58475bdf20113 100644 --- a/packages/edit-site/src/components/header/more-menu/site-export.js +++ b/packages/edit-site/src/components/header/more-menu/site-export.js @@ -44,7 +44,7 @@ export default function SiteExport() { role="menuitem" icon={ download } onClick={ handleExport } - info={ __( 'Download your templates and template parts.' ) } + info={ __( 'Download your templates and styles.' ) } > { _x( 'Export', 'site exporter menu item' ) }