From 9c926f38ec175f00168d28b1ac1d8d64b2d66597 Mon Sep 17 00:00:00 2001 From: Glen Davies Date: Tue, 6 Dec 2022 09:55:26 +1300 Subject: [PATCH 01/39] Try adding a custom CSS panel to global styles --- .../components/global-styles/screen-css.js | 56 +++++++++++++++++++ .../components/global-styles/screen-root.js | 32 +++++++++++ .../src/components/global-styles/style.scss | 3 +- .../src/components/global-styles/ui.js | 4 ++ 4 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 packages/edit-site/src/components/global-styles/screen-css.js diff --git a/packages/edit-site/src/components/global-styles/screen-css.js b/packages/edit-site/src/components/global-styles/screen-css.js new file mode 100644 index 00000000000000..9990221a9655aa --- /dev/null +++ b/packages/edit-site/src/components/global-styles/screen-css.js @@ -0,0 +1,56 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; +import { + TextareaControl, + __experimentalVStack as VStack, +} from '@wordpress/components'; +import { useSelect } from '@wordpress/data'; +import { store as coreStore } from '@wordpress/core-data'; + +/** + * Internal dependencies + */ +import ScreenHeader from './header'; +import Subtitle from './subtitle'; + +function ScreenCSS() { + /** + * Plan: + * 1: Get the custom_css post type + * 2: Get the slug of the active theme + * 3: Get the CSS content for the *active* theme only! + * 4: Fun part? Get changes to save. + * + * X. Is the TextareaControl too primitive? Is there a better choice? + * X. Add the code icon before the button text. + */ + + // So, this does not include the actual CSS, + // need to figure out why and if it is stored somewhere else? + const customCssPost = useSelect( ( select ) => { + return select( coreStore ).getEntityRecords( 'postType', 'custom_css', { + per_page: 1, + } ); + }, [] ); + + return ( + <> + +
+ + { __( 'ADDITIONAL CSS' ) } + + +
+ + ); +} + +export default ScreenCSS; diff --git a/packages/edit-site/src/components/global-styles/screen-root.js b/packages/edit-site/src/components/global-styles/screen-root.js index 0674b56319c70b..91633b4dd1f448 100644 --- a/packages/edit-site/src/components/global-styles/screen-root.js +++ b/packages/edit-site/src/components/global-styles/screen-root.js @@ -98,6 +98,38 @@ function ScreenRoot() { + + + + + + { __( + 'Customize the appearance of your site even further with CSS.' + ) } + + + + + { __( 'Custom' ) } + + + + + ); } diff --git a/packages/edit-site/src/components/global-styles/style.scss b/packages/edit-site/src/components/global-styles/style.scss index 16c9b9c418dcad..25bcf7d6738352 100644 --- a/packages/edit-site/src/components/global-styles/style.scss +++ b/packages/edit-site/src/components/global-styles/style.scss @@ -31,7 +31,8 @@ $block-preview-height: 150px; } .edit-site-global-styles-screen-heading-color, -.edit-site-global-styles-screen-typography { +.edit-site-global-styles-screen-typography, +.edit-site-global-styles-screen-css { margin: $grid-unit-20; } diff --git a/packages/edit-site/src/components/global-styles/ui.js b/packages/edit-site/src/components/global-styles/ui.js index 532a211597a81f..d7c9eed7d8474b 100644 --- a/packages/edit-site/src/components/global-styles/ui.js +++ b/packages/edit-site/src/components/global-styles/ui.js @@ -27,6 +27,7 @@ import ScreenLayout from './screen-layout'; import ScreenStyleVariations from './screen-style-variations'; import ScreenBorder from './screen-border'; import StyleBook from '../style-book'; +import ScreenCSS from './screen-css'; function GlobalStylesNavigationScreen( { className, ...props } ) { return ( @@ -191,6 +192,9 @@ function GlobalStylesUI( { isStyleBookOpened, onCloseStyleBook } ) { { isStyleBookOpened && ( ) } + + + ); } From 64d22a9ae58518a76289f7491f5f1fedf7a58a6e Mon Sep 17 00:00:00 2001 From: Carolina Nymark Date: Fri, 1 Jul 2022 14:17:46 +0200 Subject: [PATCH 02/39] Update screen-css.js --- .../components/global-styles/screen-css.js | 31 ++++++++++++++----- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/packages/edit-site/src/components/global-styles/screen-css.js b/packages/edit-site/src/components/global-styles/screen-css.js index 9990221a9655aa..7fc1755a632c6b 100644 --- a/packages/edit-site/src/components/global-styles/screen-css.js +++ b/packages/edit-site/src/components/global-styles/screen-css.js @@ -17,21 +17,38 @@ import Subtitle from './subtitle'; function ScreenCSS() { /** - * Plan: - * 1: Get the custom_css post type - * 2: Get the slug of the active theme - * 3: Get the CSS content for the *active* theme only! + * Original plan: + * 1: Get the slug of the current theme + * 2: Get the custom_css post type content for the current theme + * 3: Display the content inside the text area * 4: Fun part? Get changes to save. - * + * * X. Is the TextareaControl too primitive? Is there a better choice? * X. Add the code icon before the button text. + * X. Validate the CSS! + * + * What we learnt: + * getEntityRecords for the custom_css post type does not include the content. + * + * Plan B: Create a new global styles setting for the custom css. + * Use this new setting to display the CSS on the global styles screen. + * Add the custom_css post type to the global styles rest API endpoint, + * and use the existing PHP filters to make sure that the CSS in the + * global styles option and the Customier option matches. + * + * + * X. Use the existing methods for printing the actual CSS on the front and editors? */ + const currentTheme = useSelect( ( select ) => { + return select( coreStore ).getEntityRecords( 'root', 'theme', { + status: 'active', + } )[ 0 ].stylesheet; + }, [] ); - // So, this does not include the actual CSS, - // need to figure out why and if it is stored somewhere else? const customCssPost = useSelect( ( select ) => { return select( coreStore ).getEntityRecords( 'postType', 'custom_css', { per_page: 1, + slug: currentTheme, } ); }, [] ); From 28b5fb65fc412a628ddb7eb9779792656e5e075a Mon Sep 17 00:00:00 2001 From: Carolina Nymark Date: Tue, 5 Jul 2022 10:13:43 +0200 Subject: [PATCH 03/39] Update --- lib/compat/load.php | 170 ++++++++++++++++++ .../class-wp-rest-custom-css-controller.php | 129 +++++++++++++ lib/compat/wordpress-6.1/rest-api.php | 23 +++ .../components/global-styles/custom-css.js | 97 ++++++++++ .../components/global-styles/screen-css.js | 46 +---- 5 files changed, 422 insertions(+), 43 deletions(-) create mode 100644 lib/compat/load.php create mode 100644 lib/compat/wordpress-6.1/class-wp-rest-custom-css-controller.php create mode 100644 packages/edit-site/src/components/global-styles/custom-css.js diff --git a/lib/compat/load.php b/lib/compat/load.php new file mode 100644 index 00000000000000..df05c5fad7aa7c --- /dev/null +++ b/lib/compat/load.php @@ -0,0 +1,170 @@ +namespace = 'wp/v2'; + /* + * The rest base is different from the name of the post type, + * since it uses wp_get_custom_css(). + */ + $this->rest_base = 'customcss'; + } + + /** + * Registers the routes for the objects of the controller. + * + * @see register_rest_route() + * + * @since 6.1.0 + */ + public function register_routes() { + register_rest_route( + $this->namespace, + '/' . $this->rest_base, + array( + array( + 'methods' => WP_REST_Server::READABLE, + 'callback' => array( $this, 'get_items' ), + 'permission_callback' => array( $this, 'items_permissions_check' ), + ), + array( + 'methods' => WP_REST_Server::EDITABLE, + 'callback' => array( $this, 'update_item' ), + 'permission_callback' => array( $this, 'items_permissions_check' ), + ), + 'schema' => array( $this, 'get_public_item_schema' ), + ) + ); + } + + /** + * Retrieves the custom CSS + * + * @param WP_REST_Request $request Full details about the request. + * + * @return WP_Error|WP_REST_Response Response object on success, or WP_Error object on failure. + */ + public function get_items( $request ) { + $data = wp_get_custom_css(); + + return rest_ensure_response( $data ); + } + + /** + * Update custom CSS + * @see https://developer.wordpress.org/reference/functions/wp_update_custom_css_post + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function update_item( $request ) { + $data = wp_update_custom_css_post( $request ); + + return rest_ensure_response( $data ); + } + + /** + * Checks whether a given request has permission to read the custom CSS + * + * @param WP_REST_Request $request Full details about the request. + * + * @return WP_Error|bool True if the request has read access, WP_Error object otherwise. + */ + public function items_permissions_check( $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable + if ( ! current_user_can( 'edit_css' ) ) { + return new WP_Error( 'rest_cannot_view', __( 'Sorry, you are not allowed to view custom CSS.', 'gutenberg' ), array( 'status' => rest_authorization_required_code() ) ); + } + + return true; + } + + /** + * Custom CSS schema + * + * @return array Item schema data. + */ + public function get_item_schema() { + $schema = array( + '$schema' => 'http://json-schema.org/draft-04/schema#', + 'title' => 'custom_css', + 'type' => 'object', + 'properties' => array( + 'id' => array( + 'description' => __( 'ID of the custom CSS.', 'gutenberg' ), + 'type' => 'string', + 'context' => array( 'view', 'edit' ), + 'readonly' => true, + ), + 'theme' => array( + 'description' => __( 'The theme slug.', 'gutenberg' ), + 'type' => 'string', + 'context' => array( 'view', 'edit' ), + 'readonly' => true, + ), + 'content' => array( + 'description' => __( 'The custom CSS provided by the user.', 'gutenberg' ), + 'type' => 'string', + 'context' => array( 'view', 'edit' ), + 'readonly' => true, + ), + ), + ); + + return $this->add_additional_fields_schema( $schema ); + } +} diff --git a/lib/compat/wordpress-6.1/rest-api.php b/lib/compat/wordpress-6.1/rest-api.php index 5dd06d3aad855b..a9468753ea45e3 100644 --- a/lib/compat/wordpress-6.1/rest-api.php +++ b/lib/compat/wordpress-6.1/rest-api.php @@ -84,3 +84,26 @@ function gutenberg_register_has_archive_on_post_types_endpoint() { ); } add_action( 'rest_api_init', 'gutenberg_register_has_archive_on_post_types_endpoint' ); + +/** + * Update `custom_css` post type to show in rest + * + * @param array $args Array of arguments for registering a post type. + * @param string $post_type Post type key. + */ +function gutenberg_update_custom_css_rest( $args, $post_type ) { + if ( in_array( $post_type, array( 'custom_css' ), true ) ) { + $args['show_in_rest'] = true; + } + return $args; +} +add_filter( 'register_post_type_args', 'gutenberg_update_custom_css_rest', 10, 2 ); + +/** + * Registers the custom CSS REST API routes. + */ +function gutenberg_register_gutenberg_rest_custom_css() { + $custom_css = new WP_REST_Custom_CSS_Controller(); + $custom_css->register_routes(); +} +add_action( 'rest_api_init', 'gutenberg_register_gutenberg_rest_custom_css', 100 ); diff --git a/packages/edit-site/src/components/global-styles/custom-css.js b/packages/edit-site/src/components/global-styles/custom-css.js new file mode 100644 index 00000000000000..f27429484ad143 --- /dev/null +++ b/packages/edit-site/src/components/global-styles/custom-css.js @@ -0,0 +1,97 @@ +/** + * External dependencies + */ +import classnames from 'classnames'; + +/** + * WordPress dependencies + */ +import apiFetch from '@wordpress/api-fetch'; +import { useEffect, useState, useContext, createPortal } from '@wordpress/element'; +import { TextareaControl } from '@wordpress/components'; +import { createHigherOrderComponent } from '@wordpress/compose'; +import { addFilter } from '@wordpress/hooks'; +import { BlockList } from '@wordpress/block-editor'; +import { __ } from '@wordpress/i18n'; + +/* +function CustomCSSValue() { + const [ customCSS, getCustomCSS ] = useState(); + + useEffect( () => { + apiFetch( { + path: '/wp/v2/customcss', + } ).then( ( res ) => { + getCustomCSS( res ); + } ); + }, [] ); + + return customCSS; +} +*/ +function CustomCSSControl() { + const [ newCSS, updateCustomCSS ] = useState(); + const [ customCSS, getCustomCSS ] = useState(); + + useEffect( () => { + apiFetch( { + path: '/wp/v2/customcss', + } ).then( ( res ) => { + getCustomCSS( res ); + } ); + }, [] ); + /* + useEffect( () => { + apiFetch( { + path: '/wp/v2/customcss', + method: 'PUT', //PUT should be used for updating resources. + data: { post_cotent: newCSS }, + } ).then( ( res ) => { + console.log( res ); + } ); + }, [] ); + */ + + return ( + updateCustomCSS( value ) } + /> + ); +} + +export default CustomCSSControl; + +/** + * Override the default block element to include custom CSS. + * + * @param {Function} BlockListBlock Original component. + * + * @return {Function} Wrapped component. + */ +const withCustomCSS = createHigherOrderComponent( + ( BlockListBlock ) => ( props ) => { + /* + if ( ! customCSS ) { + return ; + } + */ + const id = `wp-custom-css-test`; + const className = classnames( props?.className, id ); + const element = useContext( BlockList.__unstableElementContext ); + + return ( + <> + { element && createPortal( , element ) } + + + ); + }, + 'withCustomCSS' +); + +addFilter( + 'editor.BlockListBlock', + 'core/editor/custom-css/with-customcss', + withCustomCSS +); diff --git a/packages/edit-site/src/components/global-styles/screen-css.js b/packages/edit-site/src/components/global-styles/screen-css.js index 7fc1755a632c6b..464d367d6d1ee7 100644 --- a/packages/edit-site/src/components/global-styles/screen-css.js +++ b/packages/edit-site/src/components/global-styles/screen-css.js @@ -2,56 +2,16 @@ * WordPress dependencies */ import { __ } from '@wordpress/i18n'; -import { - TextareaControl, - __experimentalVStack as VStack, -} from '@wordpress/components'; -import { useSelect } from '@wordpress/data'; -import { store as coreStore } from '@wordpress/core-data'; +import { __experimentalVStack as VStack } from '@wordpress/components'; /** * Internal dependencies */ import ScreenHeader from './header'; import Subtitle from './subtitle'; +import CustomCSSControl from './custom-css'; function ScreenCSS() { - /** - * Original plan: - * 1: Get the slug of the current theme - * 2: Get the custom_css post type content for the current theme - * 3: Display the content inside the text area - * 4: Fun part? Get changes to save. - * - * X. Is the TextareaControl too primitive? Is there a better choice? - * X. Add the code icon before the button text. - * X. Validate the CSS! - * - * What we learnt: - * getEntityRecords for the custom_css post type does not include the content. - * - * Plan B: Create a new global styles setting for the custom css. - * Use this new setting to display the CSS on the global styles screen. - * Add the custom_css post type to the global styles rest API endpoint, - * and use the existing PHP filters to make sure that the CSS in the - * global styles option and the Customier option matches. - * - * - * X. Use the existing methods for printing the actual CSS on the front and editors? - */ - const currentTheme = useSelect( ( select ) => { - return select( coreStore ).getEntityRecords( 'root', 'theme', { - status: 'active', - } )[ 0 ].stylesheet; - }, [] ); - - const customCssPost = useSelect( ( select ) => { - return select( coreStore ).getEntityRecords( 'postType', 'custom_css', { - per_page: 1, - slug: currentTheme, - } ); - }, [] ); - return ( <> { __( 'ADDITIONAL CSS' ) } - + From c0bfa6bf061aebbb0f49c48d6b9d08b73a2c338e Mon Sep 17 00:00:00 2001 From: George Mamadashvili Date: Tue, 29 Nov 2022 12:11:42 +0400 Subject: [PATCH 04/39] Fix fatal error and update compat directory --- lib/compat/load.php | 170 ------------------ lib/compat/wordpress-6.1/rest-api.php | 11 +- ...-gutenberg-rest-custom-css-controller.php} | 4 +- lib/compat/wordpress-6.2/rest-api.php | 9 + lib/load.php | 1 + 5 files changed, 13 insertions(+), 182 deletions(-) delete mode 100644 lib/compat/load.php rename lib/compat/{wordpress-6.1/class-wp-rest-custom-css-controller.php => wordpress-6.2/class-gutenberg-rest-custom-css-controller.php} (96%) diff --git a/lib/compat/load.php b/lib/compat/load.php deleted file mode 100644 index df05c5fad7aa7c..00000000000000 --- a/lib/compat/load.php +++ /dev/null @@ -1,170 +0,0 @@ -register_routes(); -} -add_action( 'rest_api_init', 'gutenberg_register_gutenberg_rest_custom_css', 100 ); +// add_filter( 'register_post_type_args', 'gutenberg_update_custom_css_rest', 10, 2 ); diff --git a/lib/compat/wordpress-6.1/class-wp-rest-custom-css-controller.php b/lib/compat/wordpress-6.2/class-gutenberg-rest-custom-css-controller.php similarity index 96% rename from lib/compat/wordpress-6.1/class-wp-rest-custom-css-controller.php rename to lib/compat/wordpress-6.2/class-gutenberg-rest-custom-css-controller.php index 050aea0ae74ccf..2b269fcbf9262a 100644 --- a/lib/compat/wordpress-6.1/class-wp-rest-custom-css-controller.php +++ b/lib/compat/wordpress-6.2/class-gutenberg-rest-custom-css-controller.php @@ -1,6 +1,6 @@ register_routes(); +} +add_action( 'rest_api_init', 'gutenberg_register_gutenberg_rest_custom_css' ); diff --git a/lib/load.php b/lib/load.php index 3d871e607d7fa5..3eca4479554808 100644 --- a/lib/load.php +++ b/lib/load.php @@ -44,6 +44,7 @@ function gutenberg_is_experiment_enabled( $name ) { require_once __DIR__ . '/compat/wordpress-6.2/class-gutenberg-rest-block-patterns-controller-6-2.php'; require_once __DIR__ . '/compat/wordpress-6.2/class-gutenberg-rest-block-pattern-categories-controller.php'; require_once __DIR__ . '/compat/wordpress-6.2/class-gutenberg-rest-pattern-directory-controller-6-2.php'; + require_once __DIR__ . '/compat/wordpress-6.2/class-gutenberg-rest-custom-css-controller.php'; require_once __DIR__ . '/compat/wordpress-6.2/rest-api.php'; require_once __DIR__ . '/compat/wordpress-6.2/block-patterns.php'; From 0678fa85be88d90fd3f7fb61339df3cfc17e0254 Mon Sep 17 00:00:00 2001 From: George Mamadashvili Date: Tue, 29 Nov 2022 12:13:51 +0400 Subject: [PATCH 05/39] No need to enable REST API support for custom_css post type --- lib/compat/wordpress-6.1/rest-api.php | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/lib/compat/wordpress-6.1/rest-api.php b/lib/compat/wordpress-6.1/rest-api.php index ee62ebfed65ad3..5dd06d3aad855b 100644 --- a/lib/compat/wordpress-6.1/rest-api.php +++ b/lib/compat/wordpress-6.1/rest-api.php @@ -84,17 +84,3 @@ function gutenberg_register_has_archive_on_post_types_endpoint() { ); } add_action( 'rest_api_init', 'gutenberg_register_has_archive_on_post_types_endpoint' ); - -/** - * Update `custom_css` post type to show in rest - * - * @param array $args Array of arguments for registering a post type. - * @param string $post_type Post type key. - */ -function gutenberg_update_custom_css_rest( $args, $post_type ) { - if ( in_array( $post_type, array( 'custom_css' ), true ) ) { - $args['show_in_rest'] = true; - } - return $args; -} -// add_filter( 'register_post_type_args', 'gutenberg_update_custom_css_rest', 10, 2 ); From d9cced101510d45f38b2f58819aa6a80b8fcec31 Mon Sep 17 00:00:00 2001 From: George Mamadashvili Date: Tue, 29 Nov 2022 12:25:30 +0400 Subject: [PATCH 06/39] Fix PHPLint errors --- .../class-gutenberg-rest-custom-css-controller.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/compat/wordpress-6.2/class-gutenberg-rest-custom-css-controller.php b/lib/compat/wordpress-6.2/class-gutenberg-rest-custom-css-controller.php index 2b269fcbf9262a..678c3f84a71ab1 100644 --- a/lib/compat/wordpress-6.2/class-gutenberg-rest-custom-css-controller.php +++ b/lib/compat/wordpress-6.2/class-gutenberg-rest-custom-css-controller.php @@ -18,6 +18,7 @@ class Gutenberg_REST_Custom_CSS_Controller extends WP_REST_Controller { */ public function __construct() { $this->namespace = 'wp/v2'; + /* * The rest base is different from the name of the post type, * since it uses wp_get_custom_css(). @@ -55,11 +56,9 @@ public function register_routes() { /** * Retrieves the custom CSS * - * @param WP_REST_Request $request Full details about the request. - * * @return WP_Error|WP_REST_Response Response object on success, or WP_Error object on failure. */ - public function get_items( $request ) { + public function get_items() { $data = wp_get_custom_css(); return rest_ensure_response( $data ); @@ -67,6 +66,7 @@ public function get_items( $request ) { /** * Update custom CSS + * * @see https://developer.wordpress.org/reference/functions/wp_update_custom_css_post * @param WP_REST_Request $request Full details about the request. * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. @@ -103,19 +103,19 @@ public function get_item_schema() { 'title' => 'custom_css', 'type' => 'object', 'properties' => array( - 'id' => array( + 'id' => array( 'description' => __( 'ID of the custom CSS.', 'gutenberg' ), 'type' => 'string', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), - 'theme' => array( + 'theme' => array( 'description' => __( 'The theme slug.', 'gutenberg' ), 'type' => 'string', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), - 'content' => array( + 'content' => array( 'description' => __( 'The custom CSS provided by the user.', 'gutenberg' ), 'type' => 'string', 'context' => array( 'view', 'edit' ), From a5b66c2137dda670c649fd606b715579bcdcd852 Mon Sep 17 00:00:00 2001 From: Glen Davies Date: Wed, 30 Nov 2022 16:46:13 +1300 Subject: [PATCH 07/39] Switch to using core data store instead of direct fetches to API --- ...s-gutenberg-rest-custom-css-controller.php | 9 +-- .../custom-css-custom-post-type.php | 40 +++++++++++ lib/load.php | 1 + .../components/global-styles/custom-css.js | 72 ++++++++----------- 4 files changed, 76 insertions(+), 46 deletions(-) create mode 100644 lib/compat/wordpress-6.2/custom-css-custom-post-type.php diff --git a/lib/compat/wordpress-6.2/class-gutenberg-rest-custom-css-controller.php b/lib/compat/wordpress-6.2/class-gutenberg-rest-custom-css-controller.php index 678c3f84a71ab1..788fd27d9673e5 100644 --- a/lib/compat/wordpress-6.2/class-gutenberg-rest-custom-css-controller.php +++ b/lib/compat/wordpress-6.2/class-gutenberg-rest-custom-css-controller.php @@ -11,7 +11,7 @@ * * @see WP_REST_Controller */ -class Gutenberg_REST_Custom_CSS_Controller extends WP_REST_Controller { +class Gutenberg_REST_Custom_CSS_Controller extends WP_REST_Posts_Controller { /** * Constructs the controller. @@ -23,7 +23,7 @@ public function __construct() { * The rest base is different from the name of the post type, * since it uses wp_get_custom_css(). */ - $this->rest_base = 'customcss'; + $this->rest_base = 'custom_css'; } /** @@ -61,7 +61,7 @@ public function register_routes() { public function get_items() { $data = wp_get_custom_css(); - return rest_ensure_response( $data ); + return rest_ensure_response( array('post_content' => $data ) ); } /** @@ -72,7 +72,8 @@ public function get_items() { * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. */ public function update_item( $request ) { - $data = wp_update_custom_css_post( $request ); + $new_data = $request->get_json_params(); + $data = wp_update_custom_css_post( $new_data['custom_css'] ); return rest_ensure_response( $data ); } diff --git a/lib/compat/wordpress-6.2/custom-css-custom-post-type.php b/lib/compat/wordpress-6.2/custom-css-custom-post-type.php new file mode 100644 index 00000000000000..1c567a41e274fe --- /dev/null +++ b/lib/compat/wordpress-6.2/custom-css-custom-post-type.php @@ -0,0 +1,40 @@ + array( + 'name' => __( 'Custom CSS', 'gutenberg' ), + 'singular_name' => __( 'Custom CSS', 'gutenberg' ), + ), + 'public' => false, + 'show_in_rest' => true, + 'rest_controller_class' => 'Gutenberg_REST_Custom_CSS_Controller', + 'hierarchical' => false, + 'rewrite' => false, + 'query_var' => false, + 'delete_with_user' => false, + 'can_export' => true, + '_builtin' => true, /* internal use only. don't use this when registering your own post type. */ + 'supports' => array( 'title', 'revisions' ), + 'capabilities' => array( + 'delete_posts' => 'edit_theme_options', + 'delete_post' => 'edit_theme_options', + 'delete_published_posts' => 'edit_theme_options', + 'delete_private_posts' => 'edit_theme_options', + 'delete_others_posts' => 'edit_theme_options', + 'edit_post' => 'edit_css', + 'edit_posts' => 'edit_css', + 'edit_others_posts' => 'edit_css', + 'edit_published_posts' => 'edit_css', + 'read_post' => 'read', + 'read_private_posts' => 'read', + 'publish_posts' => 'edit_theme_options', + ), + ) + ); +} +add_action( 'init', 'gutenberg_register_custom_css_post_type' ); diff --git a/lib/load.php b/lib/load.php index 3eca4479554808..279aaec12f76e8 100644 --- a/lib/load.php +++ b/lib/load.php @@ -47,6 +47,7 @@ function gutenberg_is_experiment_enabled( $name ) { require_once __DIR__ . '/compat/wordpress-6.2/class-gutenberg-rest-custom-css-controller.php'; require_once __DIR__ . '/compat/wordpress-6.2/rest-api.php'; require_once __DIR__ . '/compat/wordpress-6.2/block-patterns.php'; + require_once __DIR__ . '/compat/wordpress-6.2/custom-css-custom-post-type.php'; // Experimental. if ( ! class_exists( 'WP_Rest_Customizer_Nonces' ) ) { diff --git a/packages/edit-site/src/components/global-styles/custom-css.js b/packages/edit-site/src/components/global-styles/custom-css.js index f27429484ad143..a2b9bcec817b45 100644 --- a/packages/edit-site/src/components/global-styles/custom-css.js +++ b/packages/edit-site/src/components/global-styles/custom-css.js @@ -6,57 +6,44 @@ import classnames from 'classnames'; /** * WordPress dependencies */ -import apiFetch from '@wordpress/api-fetch'; -import { useEffect, useState, useContext, createPortal } from '@wordpress/element'; -import { TextareaControl } from '@wordpress/components'; +import { useContext, createPortal, useState } from '@wordpress/element'; +import { TextareaControl, Button } from '@wordpress/components'; import { createHigherOrderComponent } from '@wordpress/compose'; import { addFilter } from '@wordpress/hooks'; import { BlockList } from '@wordpress/block-editor'; import { __ } from '@wordpress/i18n'; +import { useSelect, useDispatch } from '@wordpress/data'; +import { store as coreStore } from '@wordpress/core-data'; -/* -function CustomCSSValue() { - const [ customCSS, getCustomCSS ] = useState(); - - useEffect( () => { - apiFetch( { - path: '/wp/v2/customcss', - } ).then( ( res ) => { - getCustomCSS( res ); - } ); - }, [] ); - - return customCSS; -} -*/ function CustomCSSControl() { - const [ newCSS, updateCustomCSS ] = useState(); - const [ customCSS, getCustomCSS ] = useState(); + const [ updatedCSS, updateCSS ] = useState(); + const customCSS = useSelect( ( select ) => { + const { getEntityRecord } = select( coreStore ); + return getEntityRecord( 'postType', 'custom_css' )?.post_content; + } ); + + const { saveEntityRecord } = useDispatch( coreStore ); - useEffect( () => { - apiFetch( { - path: '/wp/v2/customcss', - } ).then( ( res ) => { - getCustomCSS( res ); + function updateCustomCSS() { + saveEntityRecord( 'postType', 'custom_css', { + custom_css: updatedCSS, } ); - }, [] ); - /* - useEffect( () => { - apiFetch( { - path: '/wp/v2/customcss', - method: 'PUT', //PUT should be used for updating resources. - data: { post_cotent: newCSS }, - } ).then( ( res ) => { - console.log( res ); - } ); - }, [] ); - */ + } return ( - updateCustomCSS( value ) } - /> + <> + updateCSS( value ) } + /> + + ); } @@ -82,7 +69,8 @@ const withCustomCSS = createHigherOrderComponent( return ( <> - { element && createPortal( , element ) } + { element && + createPortal( , element ) } ); From 6473e7df3a3349ef5ddc8f281efce4a43a73b92b Mon Sep 17 00:00:00 2001 From: Glen Davies Date: Thu, 1 Dec 2022 11:46:01 +1300 Subject: [PATCH 08/39] Render the custom css into the site editor --- .../global-styles-renderer/index.js | 13 +++++- .../components/global-styles/custom-css.js | 45 +------------------ 2 files changed, 12 insertions(+), 46 deletions(-) diff --git a/packages/edit-site/src/components/global-styles-renderer/index.js b/packages/edit-site/src/components/global-styles-renderer/index.js index 6dc3bbd9c4a975..a9fc6bcb95a52d 100644 --- a/packages/edit-site/src/components/global-styles-renderer/index.js +++ b/packages/edit-site/src/components/global-styles-renderer/index.js @@ -3,6 +3,7 @@ */ import { useEffect } from '@wordpress/element'; import { useSelect, useDispatch } from '@wordpress/data'; +import { store as coreStore } from '@wordpress/core-data'; /** * Internal dependencies @@ -18,6 +19,10 @@ function useGlobalStylesRenderer() { const [ styles, settings, svgFilters ] = useGlobalStylesOutput(); const { getSettings } = useSelect( editSiteStore ); const { updateSettings } = useDispatch( editSiteStore ); + const customCSS = useSelect( ( select ) => { + const { getEntityRecord } = select( coreStore ); + return getEntityRecord( 'postType', 'custom_css' )?.post_content; + } ); useEffect( () => { if ( ! styles || ! settings ) { @@ -30,11 +35,15 @@ function useGlobalStylesRenderer() { ).filter( ( style ) => ! style.isGlobalStyles ); updateSettings( { ...currentStoreSettings, - styles: [ ...nonGlobalStyles, ...styles ], + styles: [ + ...nonGlobalStyles, + ...styles, + { css: customCSS, isGlobalStyles: false }, + ], svgFilters, __experimentalFeatures: settings, } ); - }, [ styles, settings ] ); + }, [ styles, settings, customCSS ] ); } export function GlobalStylesRenderer() { diff --git a/packages/edit-site/src/components/global-styles/custom-css.js b/packages/edit-site/src/components/global-styles/custom-css.js index a2b9bcec817b45..3130ed1aa4a72e 100644 --- a/packages/edit-site/src/components/global-styles/custom-css.js +++ b/packages/edit-site/src/components/global-styles/custom-css.js @@ -1,16 +1,8 @@ -/** - * External dependencies - */ -import classnames from 'classnames'; - /** * WordPress dependencies */ -import { useContext, createPortal, useState } from '@wordpress/element'; +import { useState } from '@wordpress/element'; import { TextareaControl, Button } from '@wordpress/components'; -import { createHigherOrderComponent } from '@wordpress/compose'; -import { addFilter } from '@wordpress/hooks'; -import { BlockList } from '@wordpress/block-editor'; import { __ } from '@wordpress/i18n'; import { useSelect, useDispatch } from '@wordpress/data'; import { store as coreStore } from '@wordpress/core-data'; @@ -48,38 +40,3 @@ function CustomCSSControl() { } export default CustomCSSControl; - -/** - * Override the default block element to include custom CSS. - * - * @param {Function} BlockListBlock Original component. - * - * @return {Function} Wrapped component. - */ -const withCustomCSS = createHigherOrderComponent( - ( BlockListBlock ) => ( props ) => { - /* - if ( ! customCSS ) { - return ; - } - */ - const id = `wp-custom-css-test`; - const className = classnames( props?.className, id ); - const element = useContext( BlockList.__unstableElementContext ); - - return ( - <> - { element && - createPortal( , element ) } - - - ); - }, - 'withCustomCSS' -); - -addFilter( - 'editor.BlockListBlock', - 'core/editor/custom-css/with-customcss', - withCustomCSS -); From 144cee4386084be53891793896029819f6762bb0 Mon Sep 17 00:00:00 2001 From: Glen Davies Date: Thu, 1 Dec 2022 11:18:28 +1300 Subject: [PATCH 09/39] Switch to the useEntityRecord hook --- .../global-styles-renderer/index.js | 9 +++-- .../components/global-styles/custom-css.js | 36 +++++++++++-------- 2 files changed, 26 insertions(+), 19 deletions(-) diff --git a/packages/edit-site/src/components/global-styles-renderer/index.js b/packages/edit-site/src/components/global-styles-renderer/index.js index a9fc6bcb95a52d..2c516acecfed2d 100644 --- a/packages/edit-site/src/components/global-styles-renderer/index.js +++ b/packages/edit-site/src/components/global-styles-renderer/index.js @@ -3,7 +3,7 @@ */ import { useEffect } from '@wordpress/element'; import { useSelect, useDispatch } from '@wordpress/data'; -import { store as coreStore } from '@wordpress/core-data'; +import { useEntityRecord } from '@wordpress/core-data'; /** * Internal dependencies @@ -19,10 +19,9 @@ function useGlobalStylesRenderer() { const [ styles, settings, svgFilters ] = useGlobalStylesOutput(); const { getSettings } = useSelect( editSiteStore ); const { updateSettings } = useDispatch( editSiteStore ); - const customCSS = useSelect( ( select ) => { - const { getEntityRecord } = select( coreStore ); - return getEntityRecord( 'postType', 'custom_css' )?.post_content; - } ); + + const { record } = useEntityRecord( 'postType', 'custom_css' ); + const customCSS = record?.post_content; useEffect( () => { if ( ! styles || ! settings ) { diff --git a/packages/edit-site/src/components/global-styles/custom-css.js b/packages/edit-site/src/components/global-styles/custom-css.js index 3130ed1aa4a72e..282b4882ac07fb 100644 --- a/packages/edit-site/src/components/global-styles/custom-css.js +++ b/packages/edit-site/src/components/global-styles/custom-css.js @@ -1,39 +1,47 @@ /** * WordPress dependencies */ -import { useState } from '@wordpress/element'; +import { useState, useEffect } from '@wordpress/element'; import { TextareaControl, Button } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; -import { useSelect, useDispatch } from '@wordpress/data'; -import { store as coreStore } from '@wordpress/core-data'; +import { useEntityRecord } from '@wordpress/core-data'; function CustomCSSControl() { - const [ updatedCSS, updateCSS ] = useState(); - const customCSS = useSelect( ( select ) => { - const { getEntityRecord } = select( coreStore ); - return getEntityRecord( 'postType', 'custom_css' )?.post_content; - } ); + const [ customCSS, updateCSS ] = useState(); + const { record, hasResolved, edit, save } = useEntityRecord( + 'postType', + 'custom_css' + ); - const { saveEntityRecord } = useDispatch( coreStore ); + useEffect( () => { + if ( hasResolved ) { + updateCSS( record?.post_content ); + } + }, [ hasResolved, record ] ); function updateCustomCSS() { - saveEntityRecord( 'postType', 'custom_css', { - custom_css: updatedCSS, + edit( { + custom_css: customCSS, } ); + save(); + } + + if ( ! hasResolved ) { + return __( 'Loading' ); } return ( <> updateCSS( value ) } /> ); From 49ede18bc5438b6e1ad5cf16ae202922c66b2fbd Mon Sep 17 00:00:00 2001 From: Glen Davies Date: Fri, 2 Dec 2022 09:51:28 +1300 Subject: [PATCH 10/39] remove use of custom_css post type as switching to use global styles --- ...s-gutenberg-rest-custom-css-controller.php | 130 ------------------ .../custom-css-custom-post-type.php | 40 ------ lib/compat/wordpress-6.2/rest-api.php | 9 -- lib/load.php | 2 - .../global-styles-renderer/index.js | 12 +- .../components/global-styles/custom-css.js | 24 +--- 6 files changed, 4 insertions(+), 213 deletions(-) delete mode 100644 lib/compat/wordpress-6.2/class-gutenberg-rest-custom-css-controller.php delete mode 100644 lib/compat/wordpress-6.2/custom-css-custom-post-type.php diff --git a/lib/compat/wordpress-6.2/class-gutenberg-rest-custom-css-controller.php b/lib/compat/wordpress-6.2/class-gutenberg-rest-custom-css-controller.php deleted file mode 100644 index 788fd27d9673e5..00000000000000 --- a/lib/compat/wordpress-6.2/class-gutenberg-rest-custom-css-controller.php +++ /dev/null @@ -1,130 +0,0 @@ -namespace = 'wp/v2'; - - /* - * The rest base is different from the name of the post type, - * since it uses wp_get_custom_css(). - */ - $this->rest_base = 'custom_css'; - } - - /** - * Registers the routes for the objects of the controller. - * - * @see register_rest_route() - * - * @since 6.1.0 - */ - public function register_routes() { - register_rest_route( - $this->namespace, - '/' . $this->rest_base, - array( - array( - 'methods' => WP_REST_Server::READABLE, - 'callback' => array( $this, 'get_items' ), - 'permission_callback' => array( $this, 'items_permissions_check' ), - ), - array( - 'methods' => WP_REST_Server::EDITABLE, - 'callback' => array( $this, 'update_item' ), - 'permission_callback' => array( $this, 'items_permissions_check' ), - ), - 'schema' => array( $this, 'get_public_item_schema' ), - ) - ); - } - - /** - * Retrieves the custom CSS - * - * @return WP_Error|WP_REST_Response Response object on success, or WP_Error object on failure. - */ - public function get_items() { - $data = wp_get_custom_css(); - - return rest_ensure_response( array('post_content' => $data ) ); - } - - /** - * Update custom CSS - * - * @see https://developer.wordpress.org/reference/functions/wp_update_custom_css_post - * @param WP_REST_Request $request Full details about the request. - * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. - */ - public function update_item( $request ) { - $new_data = $request->get_json_params(); - $data = wp_update_custom_css_post( $new_data['custom_css'] ); - - return rest_ensure_response( $data ); - } - - /** - * Checks whether a given request has permission to read the custom CSS - * - * @param WP_REST_Request $request Full details about the request. - * - * @return WP_Error|bool True if the request has read access, WP_Error object otherwise. - */ - public function items_permissions_check( $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable - if ( ! current_user_can( 'edit_css' ) ) { - return new WP_Error( 'rest_cannot_view', __( 'Sorry, you are not allowed to view custom CSS.', 'gutenberg' ), array( 'status' => rest_authorization_required_code() ) ); - } - - return true; - } - - /** - * Custom CSS schema - * - * @return array Item schema data. - */ - public function get_item_schema() { - $schema = array( - '$schema' => 'http://json-schema.org/draft-04/schema#', - 'title' => 'custom_css', - 'type' => 'object', - 'properties' => array( - 'id' => array( - 'description' => __( 'ID of the custom CSS.', 'gutenberg' ), - 'type' => 'string', - 'context' => array( 'view', 'edit' ), - 'readonly' => true, - ), - 'theme' => array( - 'description' => __( 'The theme slug.', 'gutenberg' ), - 'type' => 'string', - 'context' => array( 'view', 'edit' ), - 'readonly' => true, - ), - 'content' => array( - 'description' => __( 'The custom CSS provided by the user.', 'gutenberg' ), - 'type' => 'string', - 'context' => array( 'view', 'edit' ), - 'readonly' => true, - ), - ), - ); - - return $this->add_additional_fields_schema( $schema ); - } -} diff --git a/lib/compat/wordpress-6.2/custom-css-custom-post-type.php b/lib/compat/wordpress-6.2/custom-css-custom-post-type.php deleted file mode 100644 index 1c567a41e274fe..00000000000000 --- a/lib/compat/wordpress-6.2/custom-css-custom-post-type.php +++ /dev/null @@ -1,40 +0,0 @@ - array( - 'name' => __( 'Custom CSS', 'gutenberg' ), - 'singular_name' => __( 'Custom CSS', 'gutenberg' ), - ), - 'public' => false, - 'show_in_rest' => true, - 'rest_controller_class' => 'Gutenberg_REST_Custom_CSS_Controller', - 'hierarchical' => false, - 'rewrite' => false, - 'query_var' => false, - 'delete_with_user' => false, - 'can_export' => true, - '_builtin' => true, /* internal use only. don't use this when registering your own post type. */ - 'supports' => array( 'title', 'revisions' ), - 'capabilities' => array( - 'delete_posts' => 'edit_theme_options', - 'delete_post' => 'edit_theme_options', - 'delete_published_posts' => 'edit_theme_options', - 'delete_private_posts' => 'edit_theme_options', - 'delete_others_posts' => 'edit_theme_options', - 'edit_post' => 'edit_css', - 'edit_posts' => 'edit_css', - 'edit_others_posts' => 'edit_css', - 'edit_published_posts' => 'edit_css', - 'read_post' => 'read', - 'read_private_posts' => 'read', - 'publish_posts' => 'edit_theme_options', - ), - ) - ); -} -add_action( 'init', 'gutenberg_register_custom_css_post_type' ); diff --git a/lib/compat/wordpress-6.2/rest-api.php b/lib/compat/wordpress-6.2/rest-api.php index 84fc1e0bb8f1eb..4541ce0ae158c6 100644 --- a/lib/compat/wordpress-6.2/rest-api.php +++ b/lib/compat/wordpress-6.2/rest-api.php @@ -92,12 +92,3 @@ function gutenberg_pattern_directory_collection_params_6_2( $query_params ) { return $query_params; } add_filter( 'rest_pattern_directory_collection_params', 'gutenberg_pattern_directory_collection_params_6_2' ); - -/** - * Registers the custom CSS REST API routes. - */ -function gutenberg_register_gutenberg_rest_custom_css() { - $custom_css = new Gutenberg_REST_Custom_CSS_Controller(); - $custom_css->register_routes(); -} -add_action( 'rest_api_init', 'gutenberg_register_gutenberg_rest_custom_css' ); diff --git a/lib/load.php b/lib/load.php index 279aaec12f76e8..3d871e607d7fa5 100644 --- a/lib/load.php +++ b/lib/load.php @@ -44,10 +44,8 @@ function gutenberg_is_experiment_enabled( $name ) { require_once __DIR__ . '/compat/wordpress-6.2/class-gutenberg-rest-block-patterns-controller-6-2.php'; require_once __DIR__ . '/compat/wordpress-6.2/class-gutenberg-rest-block-pattern-categories-controller.php'; require_once __DIR__ . '/compat/wordpress-6.2/class-gutenberg-rest-pattern-directory-controller-6-2.php'; - require_once __DIR__ . '/compat/wordpress-6.2/class-gutenberg-rest-custom-css-controller.php'; require_once __DIR__ . '/compat/wordpress-6.2/rest-api.php'; require_once __DIR__ . '/compat/wordpress-6.2/block-patterns.php'; - require_once __DIR__ . '/compat/wordpress-6.2/custom-css-custom-post-type.php'; // Experimental. if ( ! class_exists( 'WP_Rest_Customizer_Nonces' ) ) { diff --git a/packages/edit-site/src/components/global-styles-renderer/index.js b/packages/edit-site/src/components/global-styles-renderer/index.js index 2c516acecfed2d..6dc3bbd9c4a975 100644 --- a/packages/edit-site/src/components/global-styles-renderer/index.js +++ b/packages/edit-site/src/components/global-styles-renderer/index.js @@ -3,7 +3,6 @@ */ import { useEffect } from '@wordpress/element'; import { useSelect, useDispatch } from '@wordpress/data'; -import { useEntityRecord } from '@wordpress/core-data'; /** * Internal dependencies @@ -20,9 +19,6 @@ function useGlobalStylesRenderer() { const { getSettings } = useSelect( editSiteStore ); const { updateSettings } = useDispatch( editSiteStore ); - const { record } = useEntityRecord( 'postType', 'custom_css' ); - const customCSS = record?.post_content; - useEffect( () => { if ( ! styles || ! settings ) { return; @@ -34,15 +30,11 @@ function useGlobalStylesRenderer() { ).filter( ( style ) => ! style.isGlobalStyles ); updateSettings( { ...currentStoreSettings, - styles: [ - ...nonGlobalStyles, - ...styles, - { css: customCSS, isGlobalStyles: false }, - ], + styles: [ ...nonGlobalStyles, ...styles ], svgFilters, __experimentalFeatures: settings, } ); - }, [ styles, settings, customCSS ] ); + }, [ styles, settings ] ); } export function GlobalStylesRenderer() { diff --git a/packages/edit-site/src/components/global-styles/custom-css.js b/packages/edit-site/src/components/global-styles/custom-css.js index 282b4882ac07fb..604b73fcdfa123 100644 --- a/packages/edit-site/src/components/global-styles/custom-css.js +++ b/packages/edit-site/src/components/global-styles/custom-css.js @@ -1,34 +1,14 @@ /** * WordPress dependencies */ -import { useState, useEffect } from '@wordpress/element'; +import { useState } from '@wordpress/element'; import { TextareaControl, Button } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; -import { useEntityRecord } from '@wordpress/core-data'; function CustomCSSControl() { const [ customCSS, updateCSS ] = useState(); - const { record, hasResolved, edit, save } = useEntityRecord( - 'postType', - 'custom_css' - ); - - useEffect( () => { - if ( hasResolved ) { - updateCSS( record?.post_content ); - } - }, [ hasResolved, record ] ); - - function updateCustomCSS() { - edit( { - custom_css: customCSS, - } ); - save(); - } - if ( ! hasResolved ) { - return __( 'Loading' ); - } + function updateCustomCSS() {} return ( <> From 31919b338a3129f16bb4f655ae70f794803bd605 Mon Sep 17 00:00:00 2001 From: Glen Davies Date: Fri, 2 Dec 2022 10:51:10 +1300 Subject: [PATCH 11/39] Switch to using global styles to store the custom css --- .../wordpress-6.2/class-wp-theme-json-6-2.php | 2 ++ .../components/global-styles/custom-css.js | 22 +++++++------------ .../global-styles/use-global-styles-output.js | 8 +++++-- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/lib/compat/wordpress-6.2/class-wp-theme-json-6-2.php b/lib/compat/wordpress-6.2/class-wp-theme-json-6-2.php index 3b368a10b7f303..307063e784e1ca 100644 --- a/lib/compat/wordpress-6.2/class-wp-theme-json-6-2.php +++ b/lib/compat/wordpress-6.2/class-wp-theme-json-6-2.php @@ -194,6 +194,7 @@ class WP_Theme_JSON_6_2 extends WP_Theme_JSON_6_1 { * @since 6.1.0 Added new side properties for `border`, * added new property `shadow`, * updated `blockGap` to be allowed at any level. + * @since 6.2.0 Added new property `css`. * @var array */ const VALID_STYLES = array( @@ -234,6 +235,7 @@ class WP_Theme_JSON_6_2 extends WP_Theme_JSON_6_1 { 'textDecoration' => null, 'textTransform' => null, ), + 'css' => null, ); /** diff --git a/packages/edit-site/src/components/global-styles/custom-css.js b/packages/edit-site/src/components/global-styles/custom-css.js index 604b73fcdfa123..ee492428d72f42 100644 --- a/packages/edit-site/src/components/global-styles/custom-css.js +++ b/packages/edit-site/src/components/global-styles/custom-css.js @@ -1,28 +1,22 @@ /** * WordPress dependencies */ -import { useState } from '@wordpress/element'; -import { TextareaControl, Button } from '@wordpress/components'; -import { __ } from '@wordpress/i18n'; +import { TextareaControl } from '@wordpress/components'; -function CustomCSSControl() { - const [ customCSS, updateCSS ] = useState(); +/** + * Internal dependencies + */ +import { useStyle } from './hooks'; - function updateCustomCSS() {} +function CustomCSSControl() { + const [ customCSS, setCustomCSS ] = useStyle( 'css' ); return ( <> updateCSS( value ) } + onChange={ ( value ) => setCustomCSS( value ) } /> - ); } diff --git a/packages/edit-site/src/components/global-styles/use-global-styles-output.js b/packages/edit-site/src/components/global-styles/use-global-styles-output.js index b32201fe2d2c22..8cb563d6b5609d 100644 --- a/packages/edit-site/src/components/global-styles/use-global-styles-output.js +++ b/packages/edit-site/src/components/global-styles/use-global-styles-output.js @@ -26,7 +26,7 @@ import { import { PRESET_METADATA, ROOT_BLOCK_SELECTOR, scopeSelector } from './utils'; import { getTypographyFontSizeValue } from './typography-utils'; import { GlobalStylesContext } from './context'; -import { useSetting } from './hooks'; +import { useSetting, useStyle } from './hooks'; // List of block support features that can have their related styles // generated under their own feature level selector rather than the block's. @@ -891,7 +891,7 @@ export function useGlobalStylesOutput() { const { getSettings } = select( blockEditorStore ); return !! getSettings().disableLayoutStyles; } ); - + const [ customCSS ] = useStyle( 'css' ); return useMemo( () => { if ( ! mergedConfig?.styles || ! mergedConfig?.settings ) { return []; @@ -919,6 +919,10 @@ export function useGlobalStylesOutput() { css: globalStyles, isGlobalStyles: true, }, + { + css: customCSS, + isGlobalStyles: true, + }, ]; return [ stylesheets, mergedConfig.settings, filters ]; From f13667c7658dc43b19b56c16ecd95b35c518a862 Mon Sep 17 00:00:00 2001 From: George Mamadashvili Date: Fri, 2 Dec 2022 18:23:41 +0400 Subject: [PATCH 12/39] Fix useMemo dependencies --- .../src/components/global-styles/use-global-styles-output.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/edit-site/src/components/global-styles/use-global-styles-output.js b/packages/edit-site/src/components/global-styles/use-global-styles-output.js index 8cb563d6b5609d..fd4cff26d19669 100644 --- a/packages/edit-site/src/components/global-styles/use-global-styles-output.js +++ b/packages/edit-site/src/components/global-styles/use-global-styles-output.js @@ -885,13 +885,14 @@ export function useGlobalStylesOutput() { let { merged: mergedConfig } = useContext( GlobalStylesContext ); const [ blockGap ] = useSetting( 'spacing.blockGap' ); + const [ customCSS ] = useStyle( 'css' ); const hasBlockGapSupport = blockGap !== null; const hasFallbackGapSupport = ! hasBlockGapSupport; // This setting isn't useful yet: it exists as a placeholder for a future explicit fallback styles support. const disableLayoutStyles = useSelect( ( select ) => { const { getSettings } = select( blockEditorStore ); return !! getSettings().disableLayoutStyles; } ); - const [ customCSS ] = useStyle( 'css' ); + return useMemo( () => { if ( ! mergedConfig?.styles || ! mergedConfig?.settings ) { return []; @@ -931,5 +932,6 @@ export function useGlobalStylesOutput() { hasFallbackGapSupport, mergedConfig, disableLayoutStyles, + customCSS, ] ); } From 23792ef3e6f572918245d9083ae9251859f007e9 Mon Sep 17 00:00:00 2001 From: George Mamadashvili Date: Fri, 2 Dec 2022 18:25:36 +0400 Subject: [PATCH 13/39] The 'css' value should be string --- .../src/components/global-styles/use-global-styles-output.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/edit-site/src/components/global-styles/use-global-styles-output.js b/packages/edit-site/src/components/global-styles/use-global-styles-output.js index fd4cff26d19669..fbe6b8c018628d 100644 --- a/packages/edit-site/src/components/global-styles/use-global-styles-output.js +++ b/packages/edit-site/src/components/global-styles/use-global-styles-output.js @@ -921,7 +921,7 @@ export function useGlobalStylesOutput() { isGlobalStyles: true, }, { - css: customCSS, + css: customCSS ?? '', isGlobalStyles: true, }, ]; From 28fc3b0527053bf33356a770a4b4bf97adb3ed57 Mon Sep 17 00:00:00 2001 From: Glen Davies Date: Tue, 13 Dec 2022 12:54:36 +1300 Subject: [PATCH 14/39] Add custom css to editor settings --- .../block-editor-settings.php | 2 +- .../wordpress-6.2/class-wp-theme-json-6-2.php | 109 ++++++++++++++++++ .../get-global-styles-and-settings.php | 2 +- lib/load.php | 2 +- 4 files changed, 112 insertions(+), 3 deletions(-) rename lib/compat/{wordpress-6.1 => wordpress-6.2}/block-editor-settings.php (99%) diff --git a/lib/compat/wordpress-6.1/block-editor-settings.php b/lib/compat/wordpress-6.2/block-editor-settings.php similarity index 99% rename from lib/compat/wordpress-6.1/block-editor-settings.php rename to lib/compat/wordpress-6.2/block-editor-settings.php index cafe91e787dc68..34749262e40ccd 100644 --- a/lib/compat/wordpress-6.1/block-editor-settings.php +++ b/lib/compat/wordpress-6.2/block-editor-settings.php @@ -74,7 +74,7 @@ function gutenberg_get_block_editor_settings( $settings ) { '__unstableType' => 'theme', 'isGlobalStyles' => true, ); - $actual_css = gutenberg_get_global_stylesheet( array( $block_classes['css'] ) ); + $actual_css = gutenberg_get_global_stylesheet( array( $block_classes['css'], 'customCSS' ) ); if ( '' !== $actual_css ) { $block_classes['css'] = $actual_css; $new_global_styles[] = $block_classes; diff --git a/lib/compat/wordpress-6.2/class-wp-theme-json-6-2.php b/lib/compat/wordpress-6.2/class-wp-theme-json-6-2.php index 307063e784e1ca..f29bf8b115cb61 100644 --- a/lib/compat/wordpress-6.2/class-wp-theme-json-6-2.php +++ b/lib/compat/wordpress-6.2/class-wp-theme-json-6-2.php @@ -279,4 +279,113 @@ protected static function remove_insecure_styles( $input ) { return $output; } + + /** + * Returns the stylesheet that results of processing + * the theme.json structure this object represents. + * + * @param array $types Types of styles to load. Will load all by default. It accepts: + * 'variables': only the CSS Custom Properties for presets & custom ones. + * 'styles': only the styles section in theme.json. + * 'presets': only the classes for the presets. + * 'customCSS': only the css from global styles.css. + * @param array $origins A list of origins to include. By default it includes VALID_ORIGINS. + * @param array $options An array of options for now used for internal purposes only (may change without notice). + * The options currently supported are 'scope' that makes sure all style are scoped to a given selector, + * and root_selector which overwrites and forces a given selector to be used on the root node. + * @return string Stylesheet. + */ + public function get_stylesheet( $types = array( 'variables', 'styles', 'presets', 'customCSS' ), $origins = null, $options = array() ) { + if ( null === $origins ) { + $origins = static::VALID_ORIGINS; + } + + if ( is_string( $types ) ) { + // Dispatch error and map old arguments to new ones. + _deprecated_argument( __FUNCTION__, '5.9' ); + if ( 'block_styles' === $types ) { + $types = array( 'styles', 'presets' ); + } elseif ( 'css_variables' === $types ) { + $types = array( 'variables' ); + } else { + $types = array( 'variables', 'styles', 'presets' ); + } + } + + $blocks_metadata = static::get_blocks_metadata(); + $style_nodes = static::get_style_nodes( $this->theme_json, $blocks_metadata ); + $setting_nodes = static::get_setting_nodes( $this->theme_json, $blocks_metadata ); + + $root_style_key = array_search( static::ROOT_BLOCK_SELECTOR, array_column( $style_nodes, 'selector' ), true ); + $root_settings_key = array_search( static::ROOT_BLOCK_SELECTOR, array_column( $setting_nodes, 'selector' ), true ); + + if ( ! empty( $options['scope'] ) ) { + foreach ( $setting_nodes as &$node ) { + $node['selector'] = static::scope_selector( $options['scope'], $node['selector'] ); + } + foreach ( $style_nodes as &$node ) { + $node['selector'] = static::scope_selector( $options['scope'], $node['selector'] ); + } + } + + if ( ! empty( $options['root_selector'] ) ) { + if ( false !== $root_settings_key ) { + $setting_nodes[ $root_settings_key ]['selector'] = $options['root_selector']; + } + if ( false !== $root_style_key ) { + $setting_nodes[ $root_style_key ]['selector'] = $options['root_selector']; + } + } + + $stylesheet = ''; + + if ( in_array( 'variables', $types, true ) ) { + $stylesheet .= $this->get_css_variables( $setting_nodes, $origins ); + } + + if ( in_array( 'styles', $types, true ) ) { + if ( false !== $root_style_key ) { + $stylesheet .= $this->get_root_layout_rules( $style_nodes[ $root_style_key ]['selector'], $style_nodes[ $root_style_key ] ); + } + $stylesheet .= $this->get_block_classes( $style_nodes ); + } elseif ( in_array( 'base-layout-styles', $types, true ) ) { + $root_selector = static::ROOT_BLOCK_SELECTOR; + $columns_selector = '.wp-block-columns'; + if ( ! empty( $options['scope'] ) ) { + $root_selector = static::scope_selector( $options['scope'], $root_selector ); + $columns_selector = static::scope_selector( $options['scope'], $columns_selector ); + } + if ( ! empty( $options['root_selector'] ) ) { + $root_selector = $options['root_selector']; + } + // Base layout styles are provided as part of `styles`, so only output separately if explicitly requested. + // For backwards compatibility, the Columns block is explicitly included, to support a different default gap value. + $base_styles_nodes = array( + array( + 'path' => array( 'styles' ), + 'selector' => $root_selector, + ), + array( + 'path' => array( 'styles', 'blocks', 'core/columns' ), + 'selector' => $columns_selector, + 'name' => 'core/columns', + ), + ); + + foreach ( $base_styles_nodes as $base_style_node ) { + $stylesheet .= $this->get_layout_styles( $base_style_node ); + } + } + + if ( in_array( 'presets', $types, true ) ) { + $stylesheet .= $this->get_preset_classes( $setting_nodes, $origins ); + } + + // Load the custom CSS last so it has the highest specificity. + if ( in_array( 'customCSS', $types, true ) ) { + $stylesheet .= _wp_array_get( $this->theme_json, array( 'styles', 'css' ) ); + } + + return $stylesheet; + } } diff --git a/lib/compat/wordpress-6.2/get-global-styles-and-settings.php b/lib/compat/wordpress-6.2/get-global-styles-and-settings.php index 1bf1ea23b6417f..aa207814108be2 100644 --- a/lib/compat/wordpress-6.2/get-global-styles-and-settings.php +++ b/lib/compat/wordpress-6.2/get-global-styles-and-settings.php @@ -85,7 +85,7 @@ function gutenberg_get_global_stylesheet( $types = array() ) { if ( empty( $types ) && ! $supports_theme_json ) { $types = array( 'variables', 'presets', 'base-layout-styles' ); } elseif ( empty( $types ) ) { - $types = array( 'variables', 'styles', 'presets' ); + $types = array( 'variables', 'styles', 'presets', 'customCSS' ); } /* diff --git a/lib/load.php b/lib/load.php index 3d871e607d7fa5..3b88235daf5fdf 100644 --- a/lib/load.php +++ b/lib/load.php @@ -61,7 +61,6 @@ function gutenberg_is_experiment_enabled( $name ) { // WordPress 6.1 compat. require __DIR__ . '/compat/wordpress-6.1/blocks.php'; -require __DIR__ . '/compat/wordpress-6.1/block-editor-settings.php'; require __DIR__ . '/compat/wordpress-6.1/persisted-preferences.php'; require __DIR__ . '/compat/wordpress-6.1/get-global-styles-and-settings.php'; require __DIR__ . '/compat/wordpress-6.1/class-wp-theme-json-data-gutenberg.php'; @@ -83,6 +82,7 @@ function gutenberg_is_experiment_enabled( $name ) { require __DIR__ . '/compat/wordpress-6.2/class-wp-theme-json-6-2.php'; require __DIR__ . '/compat/wordpress-6.2/edit-form-blocks.php'; require __DIR__ . '/compat/wordpress-6.2/site-editor.php'; +require __DIR__ . '/compat/wordpress-6.2/block-editor-settings.php'; // Experimental features. remove_action( 'plugins_loaded', '_wp_theme_json_webfonts_handler' ); // Turns off WP 6.0's stopgap handler for Webfonts API. From 607b48ea43a533ea8d758ae2d4f3abd49b04e51f Mon Sep 17 00:00:00 2001 From: Glen Davies Date: Mon, 5 Dec 2022 12:06:00 +1300 Subject: [PATCH 15/39] Refactor globals css in site editor now custom css in editor settings --- .../global-styles/use-global-styles-output.js | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/packages/edit-site/src/components/global-styles/use-global-styles-output.js b/packages/edit-site/src/components/global-styles/use-global-styles-output.js index fbe6b8c018628d..537842e929d808 100644 --- a/packages/edit-site/src/components/global-styles/use-global-styles-output.js +++ b/packages/edit-site/src/components/global-styles/use-global-styles-output.js @@ -26,7 +26,7 @@ import { import { PRESET_METADATA, ROOT_BLOCK_SELECTOR, scopeSelector } from './utils'; import { getTypographyFontSizeValue } from './typography-utils'; import { GlobalStylesContext } from './context'; -import { useSetting, useStyle } from './hooks'; +import { useSetting } from './hooks'; // List of block support features that can have their related styles // generated under their own feature level selector rather than the block's. @@ -792,6 +792,10 @@ export const toStyles = ( } } ); + if ( tree?.styles?.css ) { + ruleset = ruleset + tree.styles.css; + } + return ruleset; }; @@ -885,7 +889,6 @@ export function useGlobalStylesOutput() { let { merged: mergedConfig } = useContext( GlobalStylesContext ); const [ blockGap ] = useSetting( 'spacing.blockGap' ); - const [ customCSS ] = useStyle( 'css' ); const hasBlockGapSupport = blockGap !== null; const hasFallbackGapSupport = ! hasBlockGapSupport; // This setting isn't useful yet: it exists as a placeholder for a future explicit fallback styles support. const disableLayoutStyles = useSelect( ( select ) => { @@ -920,10 +923,6 @@ export function useGlobalStylesOutput() { css: globalStyles, isGlobalStyles: true, }, - { - css: customCSS ?? '', - isGlobalStyles: true, - }, ]; return [ stylesheets, mergedConfig.settings, filters ]; @@ -932,6 +931,5 @@ export function useGlobalStylesOutput() { hasFallbackGapSupport, mergedConfig, disableLayoutStyles, - customCSS, ] ); } From 2304cd3fae17848f0d61a55f68b8f48ec399d495 Mon Sep 17 00:00:00 2001 From: Glen Davies Date: Mon, 5 Dec 2022 12:26:54 +1300 Subject: [PATCH 16/39] Add test for customCSS in get_stylesheet --- phpunit/class-wp-theme-json-test.php | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/phpunit/class-wp-theme-json-test.php b/phpunit/class-wp-theme-json-test.php index 74306fa5d8ae32..61dfb7b9e44610 100644 --- a/phpunit/class-wp-theme-json-test.php +++ b/phpunit/class-wp-theme-json-test.php @@ -1497,4 +1497,24 @@ public function test_update_separator_declarations() { $this->assertEquals( $expected, $stylesheet ); } + + public function test_get_stylesheet_handles_custom_css() { + $theme_json = new WP_Theme_JSON_Gutenberg( + array( + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, + 'styles' => array( + 'css' => 'body { color:purple; }', + ), + ) + ); + + $base_styles = 'body { margin: 0;}.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }'; + + $custom_css = 'body { color:purple; }'; + + $expected = $base_styles . $custom_css; + + $this->assertEquals( $expected, $theme_json->get_stylesheet() ); + $this->assertEquals( $custom_css, $theme_json->get_stylesheet( array( 'customCSS' ) ) ); + } } From f562190b45896df7b4916db8db0b537d7dece20e Mon Sep 17 00:00:00 2001 From: Glen Davies Date: Fri, 9 Dec 2022 10:08:13 +1300 Subject: [PATCH 17/39] update rest endpoints --- ...utenberg-rest-global-styles-controller.php | 132 ++++++++++++++++++ lib/compat/wordpress-6.2/rest-api.php | 9 ++ lib/load.php | 1 + 3 files changed, 142 insertions(+) create mode 100644 lib/compat/wordpress-6.2/class-gutenberg-rest-global-styles-controller.php diff --git a/lib/compat/wordpress-6.2/class-gutenberg-rest-global-styles-controller.php b/lib/compat/wordpress-6.2/class-gutenberg-rest-global-styles-controller.php new file mode 100644 index 00000000000000..a495aed1fb83f5 --- /dev/null +++ b/lib/compat/wordpress-6.2/class-gutenberg-rest-global-styles-controller.php @@ -0,0 +1,132 @@ +get_post( $request['id'] ); + if ( is_wp_error( $post_before ) ) { + return $post_before; + } + + $changes = $this->prepare_item_for_database( $request ); + if ( is_wp_error( $changes ) ) { + return $changes; + } + + $result = wp_update_post( wp_slash( (array) $changes ), true, false ); + if ( is_wp_error( $result ) ) { + return $result; + } + + $post = get_post( $request['id'] ); + $fields_update = $this->update_additional_fields_for_object( $post, $request ); + if ( is_wp_error( $fields_update ) ) { + return $fields_update; + } + + wp_after_insert_post( $post, true, $post_before ); + + $response = $this->prepare_item_for_response( $post, $request ); + + return rest_ensure_response( $response ); + } + /** + * Prepares a single global styles config for update. + * + * @since 5.9.0 + * @since 6.2.0 Added validation of styles.css property. + * + * @param WP_REST_Request $request Request object. + * @return stdClass Changes to pass to wp_update_post. + */ + protected function prepare_item_for_database( $request ) { + $changes = new stdClass(); + $changes->ID = $request['id']; + $post = get_post( $request['id'] ); + $existing_config = array(); + if ( $post ) { + $existing_config = json_decode( $post->post_content, true ); + $json_decoding_error = json_last_error(); + if ( JSON_ERROR_NONE !== $json_decoding_error || ! isset( $existing_config['isGlobalStylesUserThemeJSON'] ) || + ! $existing_config['isGlobalStylesUserThemeJSON'] ) { + $existing_config = array(); + } + } + if ( isset( $request['styles'] ) || isset( $request['settings'] ) ) { + $config = array(); + if ( isset( $request['styles'] ) ) { + $config['styles'] = $request['styles']; + $validate_custom_css = $this->validate_custom_css( $request['styles']['css'] ); + if ( is_wp_error( $validate_custom_css ) ) { + return $validate_custom_css; + } + } elseif ( isset( $existing_config['styles'] ) ) { + $config['styles'] = $existing_config['styles']; + } + if ( isset( $request['settings'] ) ) { + $config['settings'] = $request['settings']; + } elseif ( isset( $existing_config['settings'] ) ) { + $config['settings'] = $existing_config['settings']; + } + $config['isGlobalStylesUserThemeJSON'] = true; + $config['version'] = WP_Theme_JSON_Gutenberg::LATEST_SCHEMA; + $changes->post_content = wp_json_encode( $config ); + } + // Post title. + if ( isset( $request['title'] ) ) { + if ( is_string( $request['title'] ) ) { + $changes->post_title = $request['title']; + } elseif ( ! empty( $request['title']['raw'] ) ) { + $changes->post_title = $request['title']['raw']; + } + } + return $changes; + } + + /** + * Validate style.css as valid CSS. + * + * Currently just checks for invalid markup. + * + * @since 6.2.0 + * + * @param string $css CSS to validate. + * @return true|WP_Error True if the input was validated, otherwise WP_Error. + */ + private function validate_custom_css( $css ) { + if ( preg_match( '# 400 ) + ); + } + return true; + } +} diff --git a/lib/compat/wordpress-6.2/rest-api.php b/lib/compat/wordpress-6.2/rest-api.php index 4541ce0ae158c6..4900a622b6c01b 100644 --- a/lib/compat/wordpress-6.2/rest-api.php +++ b/lib/compat/wordpress-6.2/rest-api.php @@ -92,3 +92,12 @@ function gutenberg_pattern_directory_collection_params_6_2( $query_params ) { return $query_params; } add_filter( 'rest_pattern_directory_collection_params', 'gutenberg_pattern_directory_collection_params_6_2' ); + +/** + * Registers the Global Styles REST API routes. + */ +function gutenberg_register_global_styles_endpoints() { + $editor_settings = new Gutenberg_REST_Global_Styles_Controller_6_2(); + $editor_settings->register_routes(); +} +add_action( 'rest_api_init', 'gutenberg_register_global_styles_endpoints' ); diff --git a/lib/load.php b/lib/load.php index 3b88235daf5fdf..30f506e4b9812a 100644 --- a/lib/load.php +++ b/lib/load.php @@ -46,6 +46,7 @@ function gutenberg_is_experiment_enabled( $name ) { require_once __DIR__ . '/compat/wordpress-6.2/class-gutenberg-rest-pattern-directory-controller-6-2.php'; require_once __DIR__ . '/compat/wordpress-6.2/rest-api.php'; require_once __DIR__ . '/compat/wordpress-6.2/block-patterns.php'; + require_once __DIR__ . '/compat/wordpress-6.2/class-gutenberg-rest-global-styles-controller.php'; // Experimental. if ( ! class_exists( 'WP_Rest_Customizer_Nonces' ) ) { From 76e3a78d19971f1f7b43d9311d158f7ad33c9856 Mon Sep 17 00:00:00 2001 From: Glen Davies Date: Tue, 6 Dec 2022 15:37:10 +1300 Subject: [PATCH 18/39] Fix linting issues --- ...hp => class-gutenberg-rest-global-styles-controller_6_2.php} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename lib/compat/wordpress-6.2/{class-gutenberg-rest-global-styles-controller.php => class-gutenberg-rest-global-styles-controller_6_2.php} (98%) diff --git a/lib/compat/wordpress-6.2/class-gutenberg-rest-global-styles-controller.php b/lib/compat/wordpress-6.2/class-gutenberg-rest-global-styles-controller_6_2.php similarity index 98% rename from lib/compat/wordpress-6.2/class-gutenberg-rest-global-styles-controller.php rename to lib/compat/wordpress-6.2/class-gutenberg-rest-global-styles-controller_6_2.php index a495aed1fb83f5..f0b588c6e3e9df 100644 --- a/lib/compat/wordpress-6.2/class-gutenberg-rest-global-styles-controller.php +++ b/lib/compat/wordpress-6.2/class-gutenberg-rest-global-styles-controller_6_2.php @@ -39,7 +39,7 @@ public function update_item( $request ) { return $changes; } - $result = wp_update_post( wp_slash( (array) $changes ), true, false ); + $result = wp_update_post( wp_slash( (array) $changes ), true, false ); if ( is_wp_error( $result ) ) { return $result; } From 08846c0ba5a28fe9fc6b353ed26e8e77a85389c1 Mon Sep 17 00:00:00 2001 From: Glen Davies Date: Tue, 6 Dec 2022 16:04:41 +1300 Subject: [PATCH 19/39] Fix file naming issue --- ...hp => class-gutenberg-rest-global-styles-controller-6-2.php} | 0 lib/load.php | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename lib/compat/wordpress-6.2/{class-gutenberg-rest-global-styles-controller_6_2.php => class-gutenberg-rest-global-styles-controller-6-2.php} (100%) diff --git a/lib/compat/wordpress-6.2/class-gutenberg-rest-global-styles-controller_6_2.php b/lib/compat/wordpress-6.2/class-gutenberg-rest-global-styles-controller-6-2.php similarity index 100% rename from lib/compat/wordpress-6.2/class-gutenberg-rest-global-styles-controller_6_2.php rename to lib/compat/wordpress-6.2/class-gutenberg-rest-global-styles-controller-6-2.php diff --git a/lib/load.php b/lib/load.php index 30f506e4b9812a..8c35db138e3a18 100644 --- a/lib/load.php +++ b/lib/load.php @@ -46,7 +46,7 @@ function gutenberg_is_experiment_enabled( $name ) { require_once __DIR__ . '/compat/wordpress-6.2/class-gutenberg-rest-pattern-directory-controller-6-2.php'; require_once __DIR__ . '/compat/wordpress-6.2/rest-api.php'; require_once __DIR__ . '/compat/wordpress-6.2/block-patterns.php'; - require_once __DIR__ . '/compat/wordpress-6.2/class-gutenberg-rest-global-styles-controller.php'; + require_once __DIR__ . '/compat/wordpress-6.2/class-gutenberg-rest-global-styles-controller-6-2.php'; // Experimental. if ( ! class_exists( 'WP_Rest_Customizer_Nonces' ) ) { From 4cc2a0e65416d4acadf59b983b44c026451f75bf Mon Sep 17 00:00:00 2001 From: Glen Davies Date: Wed, 7 Dec 2022 14:19:14 +1300 Subject: [PATCH 20/39] Fix issue with not being able to remove existing custom css --- packages/edit-site/src/components/global-styles/hooks.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/edit-site/src/components/global-styles/hooks.js b/packages/edit-site/src/components/global-styles/hooks.js index 86e8aa2d2a6413..c767f1a488cbfd 100644 --- a/packages/edit-site/src/components/global-styles/hooks.js +++ b/packages/edit-site/src/components/global-styles/hooks.js @@ -138,7 +138,11 @@ export function useStyle( path, blockName, source = 'all' ) { result = getValueFromVariable( mergedConfig, blockName, - get( userConfig, finalPath ) ?? get( baseConfig, finalPath ) + // The stlyes.css path is allowed to be empty, so don't revert to base if undefined. + finalPath === 'styles.css' + ? get( userConfig, finalPath ) + : get( userConfig, finalPath ) ?? + get( baseConfig, finalPath ) ); break; case 'user': From c5f05d7f85bd869f4db2ae51f407786fc6c40bc4 Mon Sep 17 00:00:00 2001 From: Glen Davies Date: Thu, 8 Dec 2022 09:02:37 +1300 Subject: [PATCH 21/39] Fix casing of php function param --- lib/compat/wordpress-6.2/block-editor-settings.php | 2 +- lib/compat/wordpress-6.2/class-wp-theme-json-6-2.php | 6 +++--- lib/compat/wordpress-6.2/get-global-styles-and-settings.php | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/compat/wordpress-6.2/block-editor-settings.php b/lib/compat/wordpress-6.2/block-editor-settings.php index 34749262e40ccd..82517d552f41ed 100644 --- a/lib/compat/wordpress-6.2/block-editor-settings.php +++ b/lib/compat/wordpress-6.2/block-editor-settings.php @@ -74,7 +74,7 @@ function gutenberg_get_block_editor_settings( $settings ) { '__unstableType' => 'theme', 'isGlobalStyles' => true, ); - $actual_css = gutenberg_get_global_stylesheet( array( $block_classes['css'], 'customCSS' ) ); + $actual_css = gutenberg_get_global_stylesheet( array( $block_classes['css'], 'custom-css' ) ); if ( '' !== $actual_css ) { $block_classes['css'] = $actual_css; $new_global_styles[] = $block_classes; diff --git a/lib/compat/wordpress-6.2/class-wp-theme-json-6-2.php b/lib/compat/wordpress-6.2/class-wp-theme-json-6-2.php index f29bf8b115cb61..351d630fd254e1 100644 --- a/lib/compat/wordpress-6.2/class-wp-theme-json-6-2.php +++ b/lib/compat/wordpress-6.2/class-wp-theme-json-6-2.php @@ -288,14 +288,14 @@ protected static function remove_insecure_styles( $input ) { * 'variables': only the CSS Custom Properties for presets & custom ones. * 'styles': only the styles section in theme.json. * 'presets': only the classes for the presets. - * 'customCSS': only the css from global styles.css. + * 'custom-css': only the css from global styles.css. * @param array $origins A list of origins to include. By default it includes VALID_ORIGINS. * @param array $options An array of options for now used for internal purposes only (may change without notice). * The options currently supported are 'scope' that makes sure all style are scoped to a given selector, * and root_selector which overwrites and forces a given selector to be used on the root node. * @return string Stylesheet. */ - public function get_stylesheet( $types = array( 'variables', 'styles', 'presets', 'customCSS' ), $origins = null, $options = array() ) { + public function get_stylesheet( $types = array( 'variables', 'styles', 'presets', 'custom-css' ), $origins = null, $options = array() ) { if ( null === $origins ) { $origins = static::VALID_ORIGINS; } @@ -382,7 +382,7 @@ public function get_stylesheet( $types = array( 'variables', 'styles', 'presets' } // Load the custom CSS last so it has the highest specificity. - if ( in_array( 'customCSS', $types, true ) ) { + if ( in_array( 'custom-css', $types, true ) ) { $stylesheet .= _wp_array_get( $this->theme_json, array( 'styles', 'css' ) ); } diff --git a/lib/compat/wordpress-6.2/get-global-styles-and-settings.php b/lib/compat/wordpress-6.2/get-global-styles-and-settings.php index aa207814108be2..b2188a92474f63 100644 --- a/lib/compat/wordpress-6.2/get-global-styles-and-settings.php +++ b/lib/compat/wordpress-6.2/get-global-styles-and-settings.php @@ -85,7 +85,7 @@ function gutenberg_get_global_stylesheet( $types = array() ) { if ( empty( $types ) && ! $supports_theme_json ) { $types = array( 'variables', 'presets', 'base-layout-styles' ); } elseif ( empty( $types ) ) { - $types = array( 'variables', 'styles', 'presets', 'customCSS' ); + $types = array( 'variables', 'styles', 'presets', 'custom-css' ); } /* From a6a67ad38e69271f5bbc71c047a68e3fbe49e863 Mon Sep 17 00:00:00 2001 From: Glen Davies Date: Thu, 8 Dec 2022 10:03:34 +1300 Subject: [PATCH 22/39] make input font monospace --- .../src/components/global-styles/custom-css.js | 12 ++++++------ .../src/components/global-styles/style.scss | 4 ++++ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/packages/edit-site/src/components/global-styles/custom-css.js b/packages/edit-site/src/components/global-styles/custom-css.js index ee492428d72f42..96ad77efdff24a 100644 --- a/packages/edit-site/src/components/global-styles/custom-css.js +++ b/packages/edit-site/src/components/global-styles/custom-css.js @@ -12,12 +12,12 @@ function CustomCSSControl() { const [ customCSS, setCustomCSS ] = useStyle( 'css' ); return ( - <> - setCustomCSS( value ) } - /> - + setCustomCSS( value ) } + rows={ 15 } + className="edit-site-global-styles__custom-css-input" + /> ); } diff --git a/packages/edit-site/src/components/global-styles/style.scss b/packages/edit-site/src/components/global-styles/style.scss index 25bcf7d6738352..52c79781317b66 100644 --- a/packages/edit-site/src/components/global-styles/style.scss +++ b/packages/edit-site/src/components/global-styles/style.scss @@ -134,3 +134,7 @@ $block-preview-height: 150px; border: $gray-200 $border-width solid; border-radius: $radius-block-ui; } + +.edit-site-global-styles__custom-css-input textarea { + font-family: Menlo, Consolas, monaco, monospace; +} From 035ce94b5c2eb591d7ba70eef26ce94d9737f5b4 Mon Sep 17 00:00:00 2001 From: Glen Davies Date: Thu, 8 Dec 2022 09:55:33 +1300 Subject: [PATCH 23/39] Move the custom css to its own stylesheet so invalid styles don't break the whole global styles css --- .../global-styles/use-global-styles-output.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/edit-site/src/components/global-styles/use-global-styles-output.js b/packages/edit-site/src/components/global-styles/use-global-styles-output.js index 537842e929d808..b078c6f2dc7719 100644 --- a/packages/edit-site/src/components/global-styles/use-global-styles-output.js +++ b/packages/edit-site/src/components/global-styles/use-global-styles-output.js @@ -26,7 +26,7 @@ import { import { PRESET_METADATA, ROOT_BLOCK_SELECTOR, scopeSelector } from './utils'; import { getTypographyFontSizeValue } from './typography-utils'; import { GlobalStylesContext } from './context'; -import { useSetting } from './hooks'; +import { useSetting, useStyle } from './hooks'; // List of block support features that can have their related styles // generated under their own feature level selector rather than the block's. @@ -792,10 +792,6 @@ export const toStyles = ( } } ); - if ( tree?.styles?.css ) { - ruleset = ruleset + tree.styles.css; - } - return ruleset; }; @@ -889,6 +885,7 @@ export function useGlobalStylesOutput() { let { merged: mergedConfig } = useContext( GlobalStylesContext ); const [ blockGap ] = useSetting( 'spacing.blockGap' ); + const [ customCSS ] = useStyle( 'css' ); const hasBlockGapSupport = blockGap !== null; const hasFallbackGapSupport = ! hasBlockGapSupport; // This setting isn't useful yet: it exists as a placeholder for a future explicit fallback styles support. const disableLayoutStyles = useSelect( ( select ) => { @@ -923,9 +920,14 @@ export function useGlobalStylesOutput() { css: globalStyles, isGlobalStyles: true, }, + // Load custom CSS in own stylesheet so that any invalid CSS entered in the input won't break all the global styles in the editor. + { + css: customCSS, + isGlobalStyles: true, + }, ]; - return [ stylesheets, mergedConfig.settings, filters ]; + return [ stylesheets, mergedConfig.settings, filters, customCSS ]; }, [ hasBlockGapSupport, hasFallbackGapSupport, From 472b8281fb657acdc97038d888917502c61d290c Mon Sep 17 00:00:00 2001 From: Glen Davies Date: Thu, 8 Dec 2022 11:40:14 +1300 Subject: [PATCH 24/39] Add custom css to its own stylesheet instead of combining with other global styles --- .../wordpress-6.1/block-editor-settings.php | 177 ++++++++++++++++++ .../wordpress-6.2/block-editor-settings.php | 148 +-------------- .../wordpress-6.2/class-wp-theme-json-6-2.php | 2 +- lib/load.php | 1 + 4 files changed, 185 insertions(+), 143 deletions(-) create mode 100644 lib/compat/wordpress-6.1/block-editor-settings.php diff --git a/lib/compat/wordpress-6.1/block-editor-settings.php b/lib/compat/wordpress-6.1/block-editor-settings.php new file mode 100644 index 00000000000000..cafe91e787dc68 --- /dev/null +++ b/lib/compat/wordpress-6.1/block-editor-settings.php @@ -0,0 +1,177 @@ +=' ) && version_compare( $wp_version, '6.0-beta1', '<' ); + $is_wp_6_0 = version_compare( $wp_version, '6.0-beta1', '>=' ); + + // Make sure the styles array exists. + // In some contexts, like the navigation editor, it doesn't. + if ( ! isset( $settings['styles'] ) ) { + $settings['styles'] = array(); + } + + // Remove existing global styles provided by core. + $styles_without_existing_global_styles = array(); + foreach ( $settings['styles'] as $style ) { + if ( + ( $is_wp_5_9 && ! gutenberg_is_global_styles_in_5_9( $style ) ) || // Can be removed when plugin minimum version is 6.0. + ( $is_wp_6_0 && ( ! isset( $style['isGlobalStyles'] ) || ! $style['isGlobalStyles'] ) ) + ) { + $styles_without_existing_global_styles[] = $style; + } + } + + // Recreate global styles. + $new_global_styles = array(); + $presets = array( + array( + 'css' => 'variables', + '__unstableType' => 'presets', + 'isGlobalStyles' => true, + ), + array( + 'css' => 'presets', + '__unstableType' => 'presets', + 'isGlobalStyles' => true, + ), + ); + foreach ( $presets as $preset_style ) { + $actual_css = gutenberg_get_global_stylesheet( array( $preset_style['css'] ) ); + if ( '' !== $actual_css ) { + $preset_style['css'] = $actual_css; + $new_global_styles[] = $preset_style; + } + } + + if ( wp_theme_has_theme_json() ) { + $block_classes = array( + 'css' => 'styles', + '__unstableType' => 'theme', + 'isGlobalStyles' => true, + ); + $actual_css = gutenberg_get_global_stylesheet( array( $block_classes['css'] ) ); + if ( '' !== $actual_css ) { + $block_classes['css'] = $actual_css; + $new_global_styles[] = $block_classes; + } + } else { + // If there is no `theme.json` file, ensure base layout styles are still available. + $block_classes = array( + 'css' => 'base-layout-styles', + '__unstableType' => 'base-layout', + 'isGlobalStyles' => true, + ); + $actual_css = gutenberg_get_global_stylesheet( array( $block_classes['css'] ) ); + if ( '' !== $actual_css ) { + $block_classes['css'] = $actual_css; + $new_global_styles[] = $block_classes; + } + } + + $settings['styles'] = array_merge( $new_global_styles, $styles_without_existing_global_styles ); + } + + // Copied from get_block_editor_settings() at wordpress-develop/block-editor.php. + $settings['__experimentalFeatures'] = gutenberg_get_global_settings(); + + if ( isset( $settings['__experimentalFeatures']['color']['palette'] ) ) { + $colors_by_origin = $settings['__experimentalFeatures']['color']['palette']; + $settings['colors'] = isset( $colors_by_origin['custom'] ) ? + $colors_by_origin['custom'] : ( + isset( $colors_by_origin['theme'] ) ? + $colors_by_origin['theme'] : + $colors_by_origin['default'] + ); + } + + if ( isset( $settings['__experimentalFeatures']['color']['gradients'] ) ) { + $gradients_by_origin = $settings['__experimentalFeatures']['color']['gradients']; + $settings['gradients'] = isset( $gradients_by_origin['custom'] ) ? + $gradients_by_origin['custom'] : ( + isset( $gradients_by_origin['theme'] ) ? + $gradients_by_origin['theme'] : + $gradients_by_origin['default'] + ); + } + + if ( isset( $settings['__experimentalFeatures']['typography']['fontSizes'] ) ) { + $font_sizes_by_origin = $settings['__experimentalFeatures']['typography']['fontSizes']; + $settings['fontSizes'] = isset( $font_sizes_by_origin['custom'] ) ? + $font_sizes_by_origin['custom'] : ( + isset( $font_sizes_by_origin['theme'] ) ? + $font_sizes_by_origin['theme'] : + $font_sizes_by_origin['default'] + ); + } + + if ( isset( $settings['__experimentalFeatures']['color']['custom'] ) ) { + $settings['disableCustomColors'] = ! $settings['__experimentalFeatures']['color']['custom']; + unset( $settings['__experimentalFeatures']['color']['custom'] ); + } + if ( isset( $settings['__experimentalFeatures']['color']['customGradient'] ) ) { + $settings['disableCustomGradients'] = ! $settings['__experimentalFeatures']['color']['customGradient']; + unset( $settings['__experimentalFeatures']['color']['customGradient'] ); + } + if ( isset( $settings['__experimentalFeatures']['typography']['customFontSize'] ) ) { + $settings['disableCustomFontSizes'] = ! $settings['__experimentalFeatures']['typography']['customFontSize']; + unset( $settings['__experimentalFeatures']['typography']['customFontSize'] ); + } + if ( isset( $settings['__experimentalFeatures']['typography']['lineHeight'] ) ) { + $settings['enableCustomLineHeight'] = $settings['__experimentalFeatures']['typography']['lineHeight']; + unset( $settings['__experimentalFeatures']['typography']['lineHeight'] ); + } + if ( isset( $settings['__experimentalFeatures']['spacing']['units'] ) ) { + $settings['enableCustomUnits'] = $settings['__experimentalFeatures']['spacing']['units']; + unset( $settings['__experimentalFeatures']['spacing']['units'] ); + } + if ( isset( $settings['__experimentalFeatures']['spacing']['padding'] ) ) { + $settings['enableCustomSpacing'] = $settings['__experimentalFeatures']['spacing']['padding']; + unset( $settings['__experimentalFeatures']['spacing']['padding'] ); + } + if ( isset( $settings['__experimentalFeatures']['spacing']['customSpacingSize'] ) ) { + $settings['disableCustomSpacingSizes'] = ! $settings['__experimentalFeatures']['spacing']['customSpacingSize']; + unset( $settings['__experimentalFeatures']['spacing']['customSpacingSize'] ); + } + + if ( isset( $settings['__experimentalFeatures']['spacing']['spacingSizes'] ) ) { + $spacing_sizes_by_origin = $settings['__experimentalFeatures']['spacing']['spacingSizes']; + $settings['spacingSizes'] = isset( $spacing_sizes_by_origin['custom'] ) ? + $spacing_sizes_by_origin['custom'] : ( + isset( $spacing_sizes_by_origin['theme'] ) ? + $spacing_sizes_by_origin['theme'] : + $spacing_sizes_by_origin['default'] + ); + } + + $settings['localAutosaveInterval'] = 15; + $settings['disableLayoutStyles'] = current_theme_supports( 'disable-layout-styles' ); + + return $settings; +} + +add_filter( 'block_editor_settings_all', 'gutenberg_get_block_editor_settings', PHP_INT_MAX ); diff --git a/lib/compat/wordpress-6.2/block-editor-settings.php b/lib/compat/wordpress-6.2/block-editor-settings.php index 82517d552f41ed..7e6a062afb5a05 100644 --- a/lib/compat/wordpress-6.2/block-editor-settings.php +++ b/lib/compat/wordpress-6.2/block-editor-settings.php @@ -12,7 +12,7 @@ * * @return array New block editor settings. */ -function gutenberg_get_block_editor_settings( $settings ) { +function gutenberg_get_block_editor_settings_6_2( $settings ) { // Set what is the context for this data request. $context = 'other'; if ( @@ -25,153 +25,17 @@ function gutenberg_get_block_editor_settings( $settings ) { } if ( 'other' === $context ) { - global $wp_version; - $is_wp_5_9 = version_compare( $wp_version, '5.9', '>=' ) && version_compare( $wp_version, '6.0-beta1', '<' ); - $is_wp_6_0 = version_compare( $wp_version, '6.0-beta1', '>=' ); - - // Make sure the styles array exists. - // In some contexts, like the navigation editor, it doesn't. - if ( ! isset( $settings['styles'] ) ) { - $settings['styles'] = array(); - } - - // Remove existing global styles provided by core. - $styles_without_existing_global_styles = array(); - foreach ( $settings['styles'] as $style ) { - if ( - ( $is_wp_5_9 && ! gutenberg_is_global_styles_in_5_9( $style ) ) || // Can be removed when plugin minimum version is 6.0. - ( $is_wp_6_0 && ( ! isset( $style['isGlobalStyles'] ) || ! $style['isGlobalStyles'] ) ) - ) { - $styles_without_existing_global_styles[] = $style; - } - } - - // Recreate global styles. - $new_global_styles = array(); - $presets = array( - array( - 'css' => 'variables', - '__unstableType' => 'presets', - 'isGlobalStyles' => true, - ), - array( - 'css' => 'presets', - '__unstableType' => 'presets', - 'isGlobalStyles' => true, - ), - ); - foreach ( $presets as $preset_style ) { - $actual_css = gutenberg_get_global_stylesheet( array( $preset_style['css'] ) ); - if ( '' !== $actual_css ) { - $preset_style['css'] = $actual_css; - $new_global_styles[] = $preset_style; - } - } - if ( wp_theme_has_theme_json() ) { - $block_classes = array( - 'css' => 'styles', - '__unstableType' => 'theme', + // Add the custom CSS as separate style sheet so any invalid CSS entered by users does not break other global styles. + $settings['styles'][] = array( + 'css' => gutenberg_get_global_stylesheet( array( 'custom-css' ) ), + '__unstableType' => 'user', 'isGlobalStyles' => true, ); - $actual_css = gutenberg_get_global_stylesheet( array( $block_classes['css'], 'custom-css' ) ); - if ( '' !== $actual_css ) { - $block_classes['css'] = $actual_css; - $new_global_styles[] = $block_classes; - } - } else { - // If there is no `theme.json` file, ensure base layout styles are still available. - $block_classes = array( - 'css' => 'base-layout-styles', - '__unstableType' => 'base-layout', - 'isGlobalStyles' => true, - ); - $actual_css = gutenberg_get_global_stylesheet( array( $block_classes['css'] ) ); - if ( '' !== $actual_css ) { - $block_classes['css'] = $actual_css; - $new_global_styles[] = $block_classes; - } } - - $settings['styles'] = array_merge( $new_global_styles, $styles_without_existing_global_styles ); - } - - // Copied from get_block_editor_settings() at wordpress-develop/block-editor.php. - $settings['__experimentalFeatures'] = gutenberg_get_global_settings(); - - if ( isset( $settings['__experimentalFeatures']['color']['palette'] ) ) { - $colors_by_origin = $settings['__experimentalFeatures']['color']['palette']; - $settings['colors'] = isset( $colors_by_origin['custom'] ) ? - $colors_by_origin['custom'] : ( - isset( $colors_by_origin['theme'] ) ? - $colors_by_origin['theme'] : - $colors_by_origin['default'] - ); - } - - if ( isset( $settings['__experimentalFeatures']['color']['gradients'] ) ) { - $gradients_by_origin = $settings['__experimentalFeatures']['color']['gradients']; - $settings['gradients'] = isset( $gradients_by_origin['custom'] ) ? - $gradients_by_origin['custom'] : ( - isset( $gradients_by_origin['theme'] ) ? - $gradients_by_origin['theme'] : - $gradients_by_origin['default'] - ); - } - - if ( isset( $settings['__experimentalFeatures']['typography']['fontSizes'] ) ) { - $font_sizes_by_origin = $settings['__experimentalFeatures']['typography']['fontSizes']; - $settings['fontSizes'] = isset( $font_sizes_by_origin['custom'] ) ? - $font_sizes_by_origin['custom'] : ( - isset( $font_sizes_by_origin['theme'] ) ? - $font_sizes_by_origin['theme'] : - $font_sizes_by_origin['default'] - ); - } - - if ( isset( $settings['__experimentalFeatures']['color']['custom'] ) ) { - $settings['disableCustomColors'] = ! $settings['__experimentalFeatures']['color']['custom']; - unset( $settings['__experimentalFeatures']['color']['custom'] ); - } - if ( isset( $settings['__experimentalFeatures']['color']['customGradient'] ) ) { - $settings['disableCustomGradients'] = ! $settings['__experimentalFeatures']['color']['customGradient']; - unset( $settings['__experimentalFeatures']['color']['customGradient'] ); - } - if ( isset( $settings['__experimentalFeatures']['typography']['customFontSize'] ) ) { - $settings['disableCustomFontSizes'] = ! $settings['__experimentalFeatures']['typography']['customFontSize']; - unset( $settings['__experimentalFeatures']['typography']['customFontSize'] ); } - if ( isset( $settings['__experimentalFeatures']['typography']['lineHeight'] ) ) { - $settings['enableCustomLineHeight'] = $settings['__experimentalFeatures']['typography']['lineHeight']; - unset( $settings['__experimentalFeatures']['typography']['lineHeight'] ); - } - if ( isset( $settings['__experimentalFeatures']['spacing']['units'] ) ) { - $settings['enableCustomUnits'] = $settings['__experimentalFeatures']['spacing']['units']; - unset( $settings['__experimentalFeatures']['spacing']['units'] ); - } - if ( isset( $settings['__experimentalFeatures']['spacing']['padding'] ) ) { - $settings['enableCustomSpacing'] = $settings['__experimentalFeatures']['spacing']['padding']; - unset( $settings['__experimentalFeatures']['spacing']['padding'] ); - } - if ( isset( $settings['__experimentalFeatures']['spacing']['customSpacingSize'] ) ) { - $settings['disableCustomSpacingSizes'] = ! $settings['__experimentalFeatures']['spacing']['customSpacingSize']; - unset( $settings['__experimentalFeatures']['spacing']['customSpacingSize'] ); - } - - if ( isset( $settings['__experimentalFeatures']['spacing']['spacingSizes'] ) ) { - $spacing_sizes_by_origin = $settings['__experimentalFeatures']['spacing']['spacingSizes']; - $settings['spacingSizes'] = isset( $spacing_sizes_by_origin['custom'] ) ? - $spacing_sizes_by_origin['custom'] : ( - isset( $spacing_sizes_by_origin['theme'] ) ? - $spacing_sizes_by_origin['theme'] : - $spacing_sizes_by_origin['default'] - ); - } - - $settings['localAutosaveInterval'] = 15; - $settings['disableLayoutStyles'] = current_theme_supports( 'disable-layout-styles' ); return $settings; } -add_filter( 'block_editor_settings_all', 'gutenberg_get_block_editor_settings', PHP_INT_MAX ); +add_filter( 'block_editor_settings_all', 'gutenberg_get_block_editor_settings_6_2', PHP_INT_MAX ); diff --git a/lib/compat/wordpress-6.2/class-wp-theme-json-6-2.php b/lib/compat/wordpress-6.2/class-wp-theme-json-6-2.php index 351d630fd254e1..fe01eb273066e2 100644 --- a/lib/compat/wordpress-6.2/class-wp-theme-json-6-2.php +++ b/lib/compat/wordpress-6.2/class-wp-theme-json-6-2.php @@ -295,7 +295,7 @@ protected static function remove_insecure_styles( $input ) { * and root_selector which overwrites and forces a given selector to be used on the root node. * @return string Stylesheet. */ - public function get_stylesheet( $types = array( 'variables', 'styles', 'presets', 'custom-css' ), $origins = null, $options = array() ) { + public function get_stylesheet( $types = array( 'variables', 'styles', 'presets' ), $origins = null, $options = array() ) { if ( null === $origins ) { $origins = static::VALID_ORIGINS; } diff --git a/lib/load.php b/lib/load.php index 8c35db138e3a18..b634b85b977e38 100644 --- a/lib/load.php +++ b/lib/load.php @@ -61,6 +61,7 @@ function gutenberg_is_experiment_enabled( $name ) { require __DIR__ . '/compat/plugin/edit-site-routes-backwards-compat.php'; // WordPress 6.1 compat. +require __DIR__ . '/compat/wordpress-6.1/block-editor-settings.php'; require __DIR__ . '/compat/wordpress-6.1/blocks.php'; require __DIR__ . '/compat/wordpress-6.1/persisted-preferences.php'; require __DIR__ . '/compat/wordpress-6.1/get-global-styles-and-settings.php'; From e8a5bf9386e347033878e90f36e7c4b4cc293296 Mon Sep 17 00:00:00 2001 From: Glen Davies Date: Thu, 8 Dec 2022 12:21:06 +1300 Subject: [PATCH 25/39] Update the option wording --- .../src/components/global-styles/screen-root.js | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/packages/edit-site/src/components/global-styles/screen-root.js b/packages/edit-site/src/components/global-styles/screen-root.js index 91633b4dd1f448..cf9fea216d5ec0 100644 --- a/packages/edit-site/src/components/global-styles/screen-root.js +++ b/packages/edit-site/src/components/global-styles/screen-root.js @@ -75,7 +75,8 @@ function ScreenRoot() { paddingTop={ 2 } /* * 13px matches the text inset of the NavigationButton (12px padding, plus the width of the button's border). - * This is an ad hoc override for this particular instance only and should be reconsidered before making into a pattern. + * This is an ad hoc override for this instance and the Addtional CSS option below. Other options for matching the + * the nav button inset should be looked at before reusing further. */ paddingX="13px" marginBottom={ 4 } @@ -105,15 +106,11 @@ function ScreenRoot() { { __( - 'Customize the appearance of your site even further with CSS.' + 'Add CSS to modify your site in ways not provided for by the existing design tools.' ) } From 83244a5b5b150d76884f5350af2cb7f81cada0b8 Mon Sep 17 00:00:00 2001 From: Glen Davies Date: Thu, 8 Dec 2022 13:32:55 +1300 Subject: [PATCH 26/39] use the merged config for custom css so theme.json settings picked up --- .../components/global-styles/use-global-styles-output.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/edit-site/src/components/global-styles/use-global-styles-output.js b/packages/edit-site/src/components/global-styles/use-global-styles-output.js index b078c6f2dc7719..d83693757b035c 100644 --- a/packages/edit-site/src/components/global-styles/use-global-styles-output.js +++ b/packages/edit-site/src/components/global-styles/use-global-styles-output.js @@ -26,7 +26,7 @@ import { import { PRESET_METADATA, ROOT_BLOCK_SELECTOR, scopeSelector } from './utils'; import { getTypographyFontSizeValue } from './typography-utils'; import { GlobalStylesContext } from './context'; -import { useSetting, useStyle } from './hooks'; +import { useSetting } from './hooks'; // List of block support features that can have their related styles // generated under their own feature level selector rather than the block's. @@ -885,7 +885,6 @@ export function useGlobalStylesOutput() { let { merged: mergedConfig } = useContext( GlobalStylesContext ); const [ blockGap ] = useSetting( 'spacing.blockGap' ); - const [ customCSS ] = useStyle( 'css' ); const hasBlockGapSupport = blockGap !== null; const hasFallbackGapSupport = ! hasBlockGapSupport; // This setting isn't useful yet: it exists as a placeholder for a future explicit fallback styles support. const disableLayoutStyles = useSelect( ( select ) => { @@ -922,12 +921,12 @@ export function useGlobalStylesOutput() { }, // Load custom CSS in own stylesheet so that any invalid CSS entered in the input won't break all the global styles in the editor. { - css: customCSS, + css: mergedConfig.styles.css ?? '', isGlobalStyles: true, }, ]; - return [ stylesheets, mergedConfig.settings, filters, customCSS ]; + return [ stylesheets, mergedConfig.settings, filters ]; }, [ hasBlockGapSupport, hasFallbackGapSupport, From 30417443eba15ade5c478413b29d78ca36e7367e Mon Sep 17 00:00:00 2001 From: Glen Davies Date: Thu, 8 Dec 2022 17:21:46 +1300 Subject: [PATCH 27/39] Use sass var for mono font --- packages/edit-site/src/components/global-styles/style.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/edit-site/src/components/global-styles/style.scss b/packages/edit-site/src/components/global-styles/style.scss index 52c79781317b66..2423156c28ffc0 100644 --- a/packages/edit-site/src/components/global-styles/style.scss +++ b/packages/edit-site/src/components/global-styles/style.scss @@ -136,5 +136,5 @@ $block-preview-height: 150px; } .edit-site-global-styles__custom-css-input textarea { - font-family: Menlo, Consolas, monaco, monospace; + font-family: $editor_html_font; } From 4794a7c2ce951c86eff36785465405a28c5110da Mon Sep 17 00:00:00 2001 From: Glen Davies Date: Thu, 8 Dec 2022 17:24:34 +1300 Subject: [PATCH 28/39] remove some irrelevant nesting --- .../wordpress-6.2/block-editor-settings.php | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/lib/compat/wordpress-6.2/block-editor-settings.php b/lib/compat/wordpress-6.2/block-editor-settings.php index 7e6a062afb5a05..d54f4195c37773 100644 --- a/lib/compat/wordpress-6.2/block-editor-settings.php +++ b/lib/compat/wordpress-6.2/block-editor-settings.php @@ -13,26 +13,22 @@ * @return array New block editor settings. */ function gutenberg_get_block_editor_settings_6_2( $settings ) { - // Set what is the context for this data request. - $context = 'other'; if ( defined( 'REST_REQUEST' ) && REST_REQUEST && isset( $_GET['context'] ) && 'mobile' === $_GET['context'] ) { - $context = 'mobile'; + return; } - if ( 'other' === $context ) { - if ( wp_theme_has_theme_json() ) { - // Add the custom CSS as separate style sheet so any invalid CSS entered by users does not break other global styles. - $settings['styles'][] = array( - 'css' => gutenberg_get_global_stylesheet( array( 'custom-css' ) ), - '__unstableType' => 'user', - 'isGlobalStyles' => true, - ); - } + if ( wp_theme_has_theme_json() ) { + // Add the custom CSS as separate style sheet so any invalid CSS entered by users does not break other global styles. + $settings['styles'][] = array( + 'css' => gutenberg_get_global_stylesheet( array( 'custom-css' ) ), + '__unstableType' => 'user', + 'isGlobalStyles' => true, + ); } return $settings; From 01a7bb4154f4a2265bbffa9727ce772bedf30758 Mon Sep 17 00:00:00 2001 From: Glen Davies Date: Thu, 8 Dec 2022 17:28:29 +1300 Subject: [PATCH 29/39] Update label wording --- packages/edit-site/src/components/global-styles/screen-css.js | 2 +- packages/edit-site/src/components/global-styles/screen-root.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/edit-site/src/components/global-styles/screen-css.js b/packages/edit-site/src/components/global-styles/screen-css.js index 464d367d6d1ee7..13cb7d95446f8d 100644 --- a/packages/edit-site/src/components/global-styles/screen-css.js +++ b/packages/edit-site/src/components/global-styles/screen-css.js @@ -17,7 +17,7 @@ function ScreenCSS() {
diff --git a/packages/edit-site/src/components/global-styles/screen-root.js b/packages/edit-site/src/components/global-styles/screen-root.js index cf9fea216d5ec0..12e9964a7e52aa 100644 --- a/packages/edit-site/src/components/global-styles/screen-root.js +++ b/packages/edit-site/src/components/global-styles/screen-root.js @@ -110,7 +110,7 @@ function ScreenRoot() { marginBottom={ 4 } > { __( - 'Add CSS to modify your site in ways not provided for by the existing design tools.' + 'Add CSS beyond the styles offered by the existing design tools.' ) } From feeea4fd1f62e80c2e095ebef7a66b25bcd53e5b Mon Sep 17 00:00:00 2001 From: George Mamadashvili Date: Thu, 8 Dec 2022 15:29:04 +0400 Subject: [PATCH 30/39] Always return settings Co-authored-by: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> --- lib/compat/wordpress-6.2/block-editor-settings.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/compat/wordpress-6.2/block-editor-settings.php b/lib/compat/wordpress-6.2/block-editor-settings.php index d54f4195c37773..7c1a6aab9d9357 100644 --- a/lib/compat/wordpress-6.2/block-editor-settings.php +++ b/lib/compat/wordpress-6.2/block-editor-settings.php @@ -19,7 +19,7 @@ function gutenberg_get_block_editor_settings_6_2( $settings ) { isset( $_GET['context'] ) && 'mobile' === $_GET['context'] ) { - return; + return $settings; } if ( wp_theme_has_theme_json() ) { From c933a607735bc517a7f60d6f8bc97a7cbadc531d Mon Sep 17 00:00:00 2001 From: Glen Davies Date: Fri, 9 Dec 2022 09:23:58 +1300 Subject: [PATCH 31/39] Remove mobile block as probably not needed --- lib/compat/wordpress-6.2/block-editor-settings.php | 9 --------- 1 file changed, 9 deletions(-) diff --git a/lib/compat/wordpress-6.2/block-editor-settings.php b/lib/compat/wordpress-6.2/block-editor-settings.php index 7c1a6aab9d9357..7323d34eb667ce 100644 --- a/lib/compat/wordpress-6.2/block-editor-settings.php +++ b/lib/compat/wordpress-6.2/block-editor-settings.php @@ -13,15 +13,6 @@ * @return array New block editor settings. */ function gutenberg_get_block_editor_settings_6_2( $settings ) { - if ( - defined( 'REST_REQUEST' ) && - REST_REQUEST && - isset( $_GET['context'] ) && - 'mobile' === $_GET['context'] - ) { - return $settings; - } - if ( wp_theme_has_theme_json() ) { // Add the custom CSS as separate style sheet so any invalid CSS entered by users does not break other global styles. $settings['styles'][] = array( From a1004ba2ab3474561177af5a1d035aa153559b29 Mon Sep 17 00:00:00 2001 From: Glen Davies Date: Fri, 9 Dec 2022 10:13:08 +1300 Subject: [PATCH 32/39] Port the prepare_items_for_response method in order to pick up new theme json handling for styles.css --- ...berg-rest-global-styles-controller-6-2.php | 59 ++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/lib/compat/wordpress-6.2/class-gutenberg-rest-global-styles-controller-6-2.php b/lib/compat/wordpress-6.2/class-gutenberg-rest-global-styles-controller-6-2.php index f0b588c6e3e9df..c3b923310edb89 100644 --- a/lib/compat/wordpress-6.2/class-gutenberg-rest-global-styles-controller-6-2.php +++ b/lib/compat/wordpress-6.2/class-gutenberg-rest-global-styles-controller-6-2.php @@ -9,7 +9,7 @@ /** * Base Global Styles REST API Controller. */ -class Gutenberg_REST_Global_Styles_Controller_6_2 extends Gutenberg_REST_Global_Styles_Controller { +class Gutenberg_REST_Global_Styles_Controller_6_2 extends WP_REST_Global_Styles_Controller { /** * Registers the controllers routes. * @@ -19,6 +19,63 @@ public function register_routes() { parent::register_routes(); } + /** + * Prepare a global styles config output for response. + * + * @since 5.9.0 + * @since 6.2 Handling of style.css was added to WP_Theme_JSON. + * + * @param WP_Post $post Global Styles post object. + * @param WP_REST_Request $request Request object. + * @return WP_REST_Response Response object. + */ + public function prepare_item_for_response( $post, $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable + $raw_config = json_decode( $post->post_content, true ); + $is_global_styles_user_theme_json = isset( $raw_config['isGlobalStylesUserThemeJSON'] ) && true === $raw_config['isGlobalStylesUserThemeJSON']; + $config = array(); + if ( $is_global_styles_user_theme_json ) { + $config = ( new WP_Theme_JSON_Gutenberg( $raw_config, 'custom' ) )->get_raw_data(); + } + // Base fields for every post. + $data = array(); + $fields = $this->get_fields_for_response( $request ); + if ( rest_is_field_included( 'id', $fields ) ) { + $data['id'] = $post->ID; + } + if ( rest_is_field_included( 'title', $fields ) ) { + $data['title'] = array(); + } + if ( rest_is_field_included( 'title.raw', $fields ) ) { + $data['title']['raw'] = $post->post_title; + } + if ( rest_is_field_included( 'title.rendered', $fields ) ) { + add_filter( 'protected_title_format', array( $this, 'protected_title_format' ) ); + $data['title']['rendered'] = get_the_title( $post->ID ); + remove_filter( 'protected_title_format', array( $this, 'protected_title_format' ) ); + } + if ( rest_is_field_included( 'settings', $fields ) ) { + $data['settings'] = ! empty( $config['settings'] ) && $is_global_styles_user_theme_json ? $config['settings'] : new stdClass(); + } + if ( rest_is_field_included( 'styles', $fields ) ) { + $data['styles'] = ! empty( $config['styles'] ) && $is_global_styles_user_theme_json ? $config['styles'] : new stdClass(); + } + $context = ! empty( $request['context'] ) ? $request['context'] : 'view'; + $data = $this->add_additional_fields_to_object( $data, $request ); + $data = $this->filter_response_by_context( $data, $context ); + // Wrap the data in a response object. + $response = rest_ensure_response( $data ); + $links = $this->prepare_links( $post->ID ); + $response->add_links( $links ); + if ( ! empty( $links['self']['href'] ) ) { + $actions = $this->get_available_actions(); + $self = $links['self']['href']; + foreach ( $actions as $rel ) { + $response->add_link( $rel, $self ); + } + } + return $response; + } + /** * Updates a single global style config. * From 414c928dbab08448d092d76b5b3dcd848c422b9b Mon Sep 17 00:00:00 2001 From: Glen Davies Date: Fri, 9 Dec 2022 10:38:27 +1300 Subject: [PATCH 33/39] make prepare_item_for_response same as core to make backporting easier --- ...berg-rest-global-styles-controller-6-2.php | 27 ++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/lib/compat/wordpress-6.2/class-gutenberg-rest-global-styles-controller-6-2.php b/lib/compat/wordpress-6.2/class-gutenberg-rest-global-styles-controller-6-2.php index c3b923310edb89..9f762dd961d058 100644 --- a/lib/compat/wordpress-6.2/class-gutenberg-rest-global-styles-controller-6-2.php +++ b/lib/compat/wordpress-6.2/class-gutenberg-rest-global-styles-controller-6-2.php @@ -36,12 +36,15 @@ public function prepare_item_for_response( $post, $request ) { // phpcs:ignore V if ( $is_global_styles_user_theme_json ) { $config = ( new WP_Theme_JSON_Gutenberg( $raw_config, 'custom' ) )->get_raw_data(); } + // Base fields for every post. $data = array(); $fields = $this->get_fields_for_response( $request ); + if ( rest_is_field_included( 'id', $fields ) ) { $data['id'] = $post->ID; } + if ( rest_is_field_included( 'title', $fields ) ) { $data['title'] = array(); } @@ -50,29 +53,39 @@ public function prepare_item_for_response( $post, $request ) { // phpcs:ignore V } if ( rest_is_field_included( 'title.rendered', $fields ) ) { add_filter( 'protected_title_format', array( $this, 'protected_title_format' ) ); + $data['title']['rendered'] = get_the_title( $post->ID ); + remove_filter( 'protected_title_format', array( $this, 'protected_title_format' ) ); } + if ( rest_is_field_included( 'settings', $fields ) ) { $data['settings'] = ! empty( $config['settings'] ) && $is_global_styles_user_theme_json ? $config['settings'] : new stdClass(); } + if ( rest_is_field_included( 'styles', $fields ) ) { $data['styles'] = ! empty( $config['styles'] ) && $is_global_styles_user_theme_json ? $config['styles'] : new stdClass(); } + $context = ! empty( $request['context'] ) ? $request['context'] : 'view'; $data = $this->add_additional_fields_to_object( $data, $request ); $data = $this->filter_response_by_context( $data, $context ); + // Wrap the data in a response object. $response = rest_ensure_response( $data ); - $links = $this->prepare_links( $post->ID ); - $response->add_links( $links ); - if ( ! empty( $links['self']['href'] ) ) { - $actions = $this->get_available_actions(); - $self = $links['self']['href']; - foreach ( $actions as $rel ) { - $response->add_link( $rel, $self ); + + if ( rest_is_field_included( '_links', $fields ) || rest_is_field_included( '_embedded', $fields ) ) { + $links = $this->prepare_links( $post->ID ); + $response->add_links( $links ); + if ( ! empty( $links['self']['href'] ) ) { + $actions = $this->get_available_actions(); + $self = $links['self']['href']; + foreach ( $actions as $rel ) { + $response->add_link( $rel, $self ); + } } } + return $response; } From abdf4a99e13ff74a7ecf07b01da31949c19ffdb2 Mon Sep 17 00:00:00 2001 From: Glen Davies Date: Mon, 12 Dec 2022 14:45:11 +1300 Subject: [PATCH 34/39] Make sure the get_user_data call is always called at least once by the plugin. --- .../class-wp-theme-json-resolver-6-2.php | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/lib/compat/wordpress-6.2/class-wp-theme-json-resolver-6-2.php b/lib/compat/wordpress-6.2/class-wp-theme-json-resolver-6-2.php index 2cce8cec7e46e1..3488a7e9205aea 100644 --- a/lib/compat/wordpress-6.2/class-wp-theme-json-resolver-6-2.php +++ b/lib/compat/wordpress-6.2/class-wp-theme-json-resolver-6-2.php @@ -168,4 +168,61 @@ public static function get_merged_data( $origin = 'custom' ) { $result->set_spacing_sizes(); return $result; } + + /** + * Returns the user's origin config. + * + * @since 6.2 Added check for the WP_Theme_JSON_Gutenberg class to prevent $user + * values set in core fron overriding the new custom css values added to VALID_STYLES. + * + * @return WP_Theme_JSON_Gutenberg Entity that holds styles for user data. + */ + public static function get_user_data() { + if ( null !== static::$user && is_a( static::$user, 'WP_Theme_JSON_Gutenberg' ) ) { + return static::$user; + } + + $config = array(); + $user_cpt = static::get_user_data_from_wp_global_styles( wp_get_theme() ); + + if ( array_key_exists( 'post_content', $user_cpt ) ) { + $decoded_data = json_decode( $user_cpt['post_content'], true ); + + $json_decoding_error = json_last_error(); + if ( JSON_ERROR_NONE !== $json_decoding_error ) { + trigger_error( 'Error when decoding a theme.json schema for user data. ' . json_last_error_msg() ); + /** + * Filters the data provided by the user for global styles & settings. + * + * @param WP_Theme_JSON_Data_Gutenberg Class to access and update the underlying data. + */ + $theme_json = apply_filters( 'wp_theme_json_data_user', new WP_Theme_JSON_Data_Gutenberg( $config, 'custom' ) ); + $config = $theme_json->get_data(); + return new WP_Theme_JSON_Gutenberg( $config, 'custom' ); + } + + // Very important to verify if the flag isGlobalStylesUserThemeJSON is true. + // If is not true the content was not escaped and is not safe. + if ( + is_array( $decoded_data ) && + isset( $decoded_data['isGlobalStylesUserThemeJSON'] ) && + $decoded_data['isGlobalStylesUserThemeJSON'] + ) { + unset( $decoded_data['isGlobalStylesUserThemeJSON'] ); + $config = $decoded_data; + } + } + + /** + * Filters the data provided by the user for global styles & settings. + * + * @param WP_Theme_JSON_Data_Gutenberg Class to access and update the underlying data. + */ + $theme_json = apply_filters( 'wp_theme_json_data_user', new WP_Theme_JSON_Data_Gutenberg( $config, 'custom' ) ); + $config = $theme_json->get_data(); + + static::$user = new WP_Theme_JSON_Gutenberg( $config, 'custom' ); + + return static::$user; + } } From 43b29dd8d5aab84e03ca71f24f028d1f91c851e6 Mon Sep 17 00:00:00 2001 From: Glen Davies Date: Mon, 12 Dec 2022 15:08:08 +1300 Subject: [PATCH 35/39] Fix test and linting issues --- .../wordpress-6.2/class-wp-theme-json-resolver-6-2.php | 4 ++-- phpunit/class-wp-theme-json-test.php | 8 +------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/lib/compat/wordpress-6.2/class-wp-theme-json-resolver-6-2.php b/lib/compat/wordpress-6.2/class-wp-theme-json-resolver-6-2.php index 3488a7e9205aea..2f52a3b169258f 100644 --- a/lib/compat/wordpress-6.2/class-wp-theme-json-resolver-6-2.php +++ b/lib/compat/wordpress-6.2/class-wp-theme-json-resolver-6-2.php @@ -218,8 +218,8 @@ public static function get_user_data() { * * @param WP_Theme_JSON_Data_Gutenberg Class to access and update the underlying data. */ - $theme_json = apply_filters( 'wp_theme_json_data_user', new WP_Theme_JSON_Data_Gutenberg( $config, 'custom' ) ); - $config = $theme_json->get_data(); + $theme_json = apply_filters( 'wp_theme_json_data_user', new WP_Theme_JSON_Data_Gutenberg( $config, 'custom' ) ); + $config = $theme_json->get_data(); static::$user = new WP_Theme_JSON_Gutenberg( $config, 'custom' ); diff --git a/phpunit/class-wp-theme-json-test.php b/phpunit/class-wp-theme-json-test.php index 61dfb7b9e44610..a5413766ca7ddd 100644 --- a/phpunit/class-wp-theme-json-test.php +++ b/phpunit/class-wp-theme-json-test.php @@ -1508,13 +1508,7 @@ public function test_get_stylesheet_handles_custom_css() { ) ); - $base_styles = 'body { margin: 0;}.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }'; - $custom_css = 'body { color:purple; }'; - - $expected = $base_styles . $custom_css; - - $this->assertEquals( $expected, $theme_json->get_stylesheet() ); - $this->assertEquals( $custom_css, $theme_json->get_stylesheet( array( 'customCSS' ) ) ); + $this->assertEquals( $custom_css, $theme_json->get_stylesheet( array( 'custom-css' ) ) ); } } From d716585d56053126b5e7a630301b0078ec6bea70 Mon Sep 17 00:00:00 2001 From: Glen Davies Date: Mon, 12 Dec 2022 16:25:46 +1300 Subject: [PATCH 36/39] Use instanceof instead of is_a --- lib/compat/wordpress-6.2/class-wp-theme-json-resolver-6-2.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/compat/wordpress-6.2/class-wp-theme-json-resolver-6-2.php b/lib/compat/wordpress-6.2/class-wp-theme-json-resolver-6-2.php index 2f52a3b169258f..110c8bac7b147c 100644 --- a/lib/compat/wordpress-6.2/class-wp-theme-json-resolver-6-2.php +++ b/lib/compat/wordpress-6.2/class-wp-theme-json-resolver-6-2.php @@ -174,11 +174,13 @@ public static function get_merged_data( $origin = 'custom' ) { * * @since 6.2 Added check for the WP_Theme_JSON_Gutenberg class to prevent $user * values set in core fron overriding the new custom css values added to VALID_STYLES. + * This does not need to be backported to core as the new VALID_STYLES[css] value will + * be added to core with 6.2. * * @return WP_Theme_JSON_Gutenberg Entity that holds styles for user data. */ public static function get_user_data() { - if ( null !== static::$user && is_a( static::$user, 'WP_Theme_JSON_Gutenberg' ) ) { + if ( null !== static::$user && static::$user instanceof WP_Theme_JSON_Gutenberg ) { return static::$user; } From 1df72bf8d0a0862707702545f4ca91d89c805eca Mon Sep 17 00:00:00 2001 From: Glen Davies Date: Tue, 13 Dec 2022 11:39:31 +1300 Subject: [PATCH 37/39] Add theme.json custom css to input box --- .../components/global-styles/custom-css.js | 54 ++++++++++++++++--- .../src/components/global-styles/style.scss | 8 +++ 2 files changed, 55 insertions(+), 7 deletions(-) diff --git a/packages/edit-site/src/components/global-styles/custom-css.js b/packages/edit-site/src/components/global-styles/custom-css.js index 96ad77efdff24a..aff1c34dcd89f4 100644 --- a/packages/edit-site/src/components/global-styles/custom-css.js +++ b/packages/edit-site/src/components/global-styles/custom-css.js @@ -1,7 +1,8 @@ /** * WordPress dependencies */ -import { TextareaControl } from '@wordpress/components'; +import { TextareaControl, Panel, PanelBody } from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; /** * Internal dependencies @@ -10,14 +11,53 @@ import { useStyle } from './hooks'; function CustomCSSControl() { const [ customCSS, setCustomCSS ] = useStyle( 'css' ); + const [ themeCSS ] = useStyle( 'css', null, 'base' ); + const ignoreThemeCustomCSS = '/* IgnoreThemeCustomCSS */'; + + const themeCustomCSS = + ! customCSS && themeCSS + ? `/* ${ __( + 'Theme Custom CSS start' + ) } */\n${ themeCSS }\n/* ${ __( 'Theme Custom CSS end' ) } */` + : undefined; + + function handleOnChange( value ) { + if ( themeCSS && value === '' ) { + setCustomCSS( ignoreThemeCustomCSS ); + return; + } + setCustomCSS( value ); + } + + const originalThemeCustomCSS = + themeCSS && customCSS && themeCustomCSS !== customCSS + ? themeCSS + : undefined; return ( - setCustomCSS( value ) } - rows={ 15 } - className="edit-site-global-styles__custom-css-input" - /> + <> + handleOnChange( value ) } + rows={ 15 } + className="edit-site-global-styles__custom-css-input" + /> + { originalThemeCustomCSS && ( + + +
+							{ originalThemeCustomCSS }
+						
+
+
+ ) } + ); } diff --git a/packages/edit-site/src/components/global-styles/style.scss b/packages/edit-site/src/components/global-styles/style.scss index 2423156c28ffc0..5616a068b594c8 100644 --- a/packages/edit-site/src/components/global-styles/style.scss +++ b/packages/edit-site/src/components/global-styles/style.scss @@ -138,3 +138,11 @@ $block-preview-height: 150px; .edit-site-global-styles__custom-css-input textarea { font-family: $editor_html_font; } + +.edit-site-global-styles__custom-css-theme-css { + width: 100%; + line-break: anywhere; + white-space: break-spaces; + max-height: 200px; + overflow-y: scroll; +} From 47a6d915f8553a45d9d2702e0d372e883ac3151e Mon Sep 17 00:00:00 2001 From: Glen Davies Date: Tue, 13 Dec 2022 13:05:22 +1300 Subject: [PATCH 38/39] Add explanatory comments --- .../edit-site/src/components/global-styles/custom-css.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/edit-site/src/components/global-styles/custom-css.js b/packages/edit-site/src/components/global-styles/custom-css.js index aff1c34dcd89f4..f9af41bd69459b 100644 --- a/packages/edit-site/src/components/global-styles/custom-css.js +++ b/packages/edit-site/src/components/global-styles/custom-css.js @@ -14,6 +14,9 @@ function CustomCSSControl() { const [ themeCSS ] = useStyle( 'css', null, 'base' ); const ignoreThemeCustomCSS = '/* IgnoreThemeCustomCSS */'; + // If there is custom css from theme.json show it in the edit box + // so the user can selectively overwrite it, rather than have the user CSS + // completely overwrite the theme CSS by default. const themeCustomCSS = ! customCSS && themeCSS ? `/* ${ __( @@ -22,6 +25,8 @@ function CustomCSSControl() { : undefined; function handleOnChange( value ) { + // If there is theme custom CSS, but the user clears the input box then save the + // ignoreThemeCustomCSS string so that the theme custom CSS is not re-applied. if ( themeCSS && value === '' ) { setCustomCSS( ignoreThemeCustomCSS ); return; From b55429d4beb37e842767eb61e186dec78ff70c02 Mon Sep 17 00:00:00 2001 From: Glen Davies Date: Tue, 13 Dec 2022 14:39:32 +1300 Subject: [PATCH 39/39] Changes from code review --- packages/edit-site/src/components/global-styles/custom-css.js | 4 ++++ packages/edit-site/src/components/global-styles/screen-css.js | 2 +- .../edit-site/src/components/global-styles/screen-root.js | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/edit-site/src/components/global-styles/custom-css.js b/packages/edit-site/src/components/global-styles/custom-css.js index f9af41bd69459b..6c7d3de1cf06e5 100644 --- a/packages/edit-site/src/components/global-styles/custom-css.js +++ b/packages/edit-site/src/components/global-styles/custom-css.js @@ -49,6 +49,10 @@ function CustomCSSControl() { onChange={ ( value ) => handleOnChange( value ) } rows={ 15 } className="edit-site-global-styles__custom-css-input" + spellCheck={ false } + help={ __( + "Enter your custom CSS in the textarea and preview in the editor. Changes won't take effect until you've saved the template." + ) } /> { originalThemeCustomCSS && ( diff --git a/packages/edit-site/src/components/global-styles/screen-css.js b/packages/edit-site/src/components/global-styles/screen-css.js index 13cb7d95446f8d..74480a0677bd16 100644 --- a/packages/edit-site/src/components/global-styles/screen-css.js +++ b/packages/edit-site/src/components/global-styles/screen-css.js @@ -17,7 +17,7 @@ function ScreenCSS() {
diff --git a/packages/edit-site/src/components/global-styles/screen-root.js b/packages/edit-site/src/components/global-styles/screen-root.js index 12e9964a7e52aa..ecb68d27b7f4d7 100644 --- a/packages/edit-site/src/components/global-styles/screen-root.js +++ b/packages/edit-site/src/components/global-styles/screen-root.js @@ -110,7 +110,7 @@ function ScreenRoot() { marginBottom={ 4 } > { __( - 'Add CSS beyond the styles offered by the existing design tools.' + 'Add your own CSS to customize the appearance and layout of your site.' ) }